@@ -291,18 +291,65 @@ public static function move2trash($file_path, $ownerOnly = false) {
291291
292292 $ configuredTrashbinSize = static ::getConfiguredTrashbinSize ($ owner );
293293 if ($ configuredTrashbinSize >= 0 && $ sourceInfo ->getSize () >= $ configuredTrashbinSize ) {
294+ $ trashStorage ->releaseLock ($ trashInternalPath , ILockingProvider::LOCK_EXCLUSIVE , $ lockingProvider );
294295 return false ;
295296 }
296297
298+ // there is still a possibility that the file has been deleted by a remote user
299+ $ deletedBy = self ::overwriteDeletedBy ($ user );
300+
301+ $ query = Server::get (IDBConnection::class)->getQueryBuilder ();
302+ $ query ->insert ('files_trash ' )
303+ ->setValue ('id ' , $ query ->createNamedParameter ($ filename ))
304+ ->setValue ('timestamp ' , $ query ->createNamedParameter ($ timestamp ))
305+ ->setValue ('location ' , $ query ->createNamedParameter ($ location ))
306+ ->setValue ('user ' , $ query ->createNamedParameter ($ owner ))
307+ ->setValue ('deleted_by ' , $ query ->createNamedParameter ($ deletedBy ));
308+ $ inserted = false ;
297309 try {
298- $ moveSuccessful = true ;
310+ $ inserted = ($ query ->executeStatement () === 1 );
311+ } catch (\Throwable $ e ) {
312+ Server::get (LoggerInterface::class)->error (
313+ 'trash bin database insert failed ' ,
314+ [
315+ 'app ' => 'files_trashbin ' ,
316+ 'exception ' => $ e ,
317+ 'user ' => $ owner ,
318+ 'filename ' => $ filename ,
319+ 'timestamp ' => $ timestamp ,
320+ ]
321+ );
322+ }
323+ if (!$ inserted ) {
324+ Server::get (LoggerInterface::class)->error (
325+ 'trash bin database couldn \'t be updated, skipping trash move ' ,
326+ [
327+ 'app ' => 'files_trashbin ' ,
328+ 'user ' => $ owner ,
329+ 'filename ' => $ filename ,
330+ 'timestamp ' => $ timestamp ,
331+ ]
332+ );
333+ $ trashStorage ->releaseLock ($ trashInternalPath , ILockingProvider::LOCK_EXCLUSIVE , $ lockingProvider );
334+ return false ;
335+ }
299336
337+ $ moveSuccessful = true ;
338+ try {
300339 $ inCache = $ sourceStorage ->getCache ()->inCache ($ sourceInternalPath );
301340 $ trashStorage ->moveFromStorage ($ sourceStorage , $ sourceInternalPath , $ trashInternalPath );
302341 if ($ inCache ) {
303342 $ trashStorage ->getUpdater ()->renameFromStorage ($ sourceStorage , $ sourceInternalPath , $ trashInternalPath );
343+ } else {
344+ $ sizeDifference = $ sourceInfo ->getSize ();
345+ if ($ sizeDifference < 0 ) {
346+ $ sizeDifference = null ;
347+ } else {
348+ $ sizeDifference = (int )$ sizeDifference ;
349+ }
350+ $ trashStorage ->getUpdater ()->update ($ trashInternalPath , null , $ sizeDifference );
304351 }
305- } catch (CopyRecursiveException $ e ) {
352+ } catch (\ Exception $ e ) {
306353 $ moveSuccessful = false ;
307354 if ($ trashStorage ->file_exists ($ trashInternalPath )) {
308355 $ trashStorage ->unlink ($ trashInternalPath );
@@ -323,24 +370,31 @@ public static function move2trash($file_path, $ownerOnly = false) {
323370 } else {
324371 $ trashStorage ->getUpdater ()->remove ($ trashInternalPath );
325372 }
326- return false ;
373+ $ moveSuccessful = false ;
327374 }
328375
329- if ($ moveSuccessful ) {
330- // there is still a possibility that the file has been deleted by a remote user
331- $ deletedBy = self ::overwriteDeletedBy ($ user );
332-
333- $ query = \OC ::$ server ->getDatabaseConnection ()->getQueryBuilder ();
334- $ query ->insert ('files_trash ' )
335- ->setValue ('id ' , $ query ->createNamedParameter ($ filename ))
336- ->setValue ('timestamp ' , $ query ->createNamedParameter ($ timestamp ))
337- ->setValue ('location ' , $ query ->createNamedParameter ($ location ))
338- ->setValue ('user ' , $ query ->createNamedParameter ($ owner ))
339- ->setValue ('deleted_by ' , $ query ->createNamedParameter ($ deletedBy ));
340- $ result = $ query ->executeStatement ();
341- if (!$ result ) {
342- \OC ::$ server ->get (LoggerInterface::class)->error ('trash bin database couldn \'t be updated ' , ['app ' => 'files_trashbin ' ]);
376+ if (!$ moveSuccessful ) {
377+ Server::get (LoggerInterface::class)->error (
378+ 'trash move failed, removing trash metadata and payload ' ,
379+ [
380+ 'app ' => 'files_trashbin ' ,
381+ 'user ' => $ owner ,
382+ 'filename ' => $ filename ,
383+ 'timestamp ' => $ timestamp ,
384+ ]
385+ );
386+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
387+ if ($ trashStorage ->file_exists ($ trashInternalPath )) {
388+ if ($ trashStorage ->is_dir ($ trashInternalPath )) {
389+ $ trashStorage ->rmdir ($ trashInternalPath );
390+ } else {
391+ $ trashStorage ->unlink ($ trashInternalPath );
392+ }
343393 }
394+ $ trashStorage ->getUpdater ()->remove ($ trashInternalPath );
395+ }
396+
397+ if ($ moveSuccessful ) {
344398 Util::emitHook ('\OCA\Files_Trashbin\Trashbin ' , 'post_moveToTrash ' , ['filePath ' => Filesystem::normalizePath ($ file_path ),
345399 'trashPath ' => Filesystem::normalizePath (static ::getTrashFilename ($ filename , $ timestamp ))]);
346400
@@ -528,12 +582,7 @@ public static function restore($file, $filename, $timestamp) {
528582 self ::restoreVersions ($ view , $ file , $ filename , $ uniqueFilename , $ location , $ timestamp );
529583
530584 if ($ timestamp ) {
531- $ query = \OC ::$ server ->getDatabaseConnection ()->getQueryBuilder ();
532- $ query ->delete ('files_trash ' )
533- ->where ($ query ->expr ()->eq ('user ' , $ query ->createNamedParameter ($ user )))
534- ->andWhere ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ filename )))
535- ->andWhere ($ query ->expr ()->eq ('timestamp ' , $ query ->createNamedParameter ($ timestamp )));
536- $ query ->executeStatement ();
585+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
537586 }
538587
539588 return true ;
@@ -672,13 +721,6 @@ public static function delete($filename, $user, $timestamp = null) {
672721 $ size = 0 ;
673722
674723 if ($ timestamp ) {
675- $ query = \OC ::$ server ->getDatabaseConnection ()->getQueryBuilder ();
676- $ query ->delete ('files_trash ' )
677- ->where ($ query ->expr ()->eq ('user ' , $ query ->createNamedParameter ($ user )))
678- ->andWhere ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ filename )))
679- ->andWhere ($ query ->expr ()->eq ('timestamp ' , $ query ->createNamedParameter ($ timestamp )));
680- $ query ->executeStatement ();
681-
682724 $ file = static ::getTrashFilename ($ filename , $ timestamp );
683725 } else {
684726 $ file = $ filename ;
@@ -689,6 +731,9 @@ public static function delete($filename, $user, $timestamp = null) {
689731 try {
690732 $ node = $ userRoot ->get ('/files_trashbin/files/ ' . $ file );
691733 } catch (NotFoundException $ e ) {
734+ if ($ timestamp ) {
735+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
736+ }
692737 return $ size ;
693738 }
694739
@@ -702,9 +747,22 @@ public static function delete($filename, $user, $timestamp = null) {
702747 $ node ->delete ();
703748 self ::emitTrashbinPostDelete ('/files_trashbin/files/ ' . $ file );
704749
750+ if ($ timestamp ) {
751+ self ::deleteTrashRow ($ user , $ filename , $ timestamp );
752+ }
753+
705754 return $ size ;
706755 }
707756
757+ private static function deleteTrashRow (string $ user , string $ filename , int $ timestamp ): void {
758+ $ query = Server::get (IDBConnection::class)->getQueryBuilder ();
759+ $ query ->delete ('files_trash ' )
760+ ->where ($ query ->expr ()->eq ('user ' , $ query ->createNamedParameter ($ user )))
761+ ->andWhere ($ query ->expr ()->eq ('id ' , $ query ->createNamedParameter ($ filename )))
762+ ->andWhere ($ query ->expr ()->eq ('timestamp ' , $ query ->createNamedParameter ($ timestamp )));
763+ $ query ->executeStatement ();
764+ }
765+
708766 /**
709767 * @param string $file
710768 * @param string $filename
0 commit comments