Completed
Pull Request — master (#3829)
by Maxence
12:57
created
apps/comments/appinfo/app.php 1 patch
Indentation   +37 added lines, -37 removed lines patch added patch discarded remove patch
@@ -23,54 +23,54 @@
 block discarded – undo
23 23
 
24 24
 $eventDispatcher = \OC::$server->getEventDispatcher();
25 25
 $eventDispatcher->addListener(
26
-	'OCA\Files::loadAdditionalScripts',
27
-	function() {
28
-		\OCP\Util::addScript('oc-backbone-webdav');
29
-		\OCP\Util::addScript('comments', 'app');
30
-		\OCP\Util::addScript('comments', 'commentmodel');
31
-		\OCP\Util::addScript('comments', 'commentcollection');
32
-		\OCP\Util::addScript('comments', 'commentsummarymodel');
33
-		\OCP\Util::addScript('comments', 'commentstabview');
34
-		\OCP\Util::addScript('comments', 'filesplugin');
35
-		\OCP\Util::addScript('comments', 'activitytabviewplugin');
36
-		\OCP\Util::addStyle('comments', 'comments');
37
-	}
26
+    'OCA\Files::loadAdditionalScripts',
27
+    function() {
28
+        \OCP\Util::addScript('oc-backbone-webdav');
29
+        \OCP\Util::addScript('comments', 'app');
30
+        \OCP\Util::addScript('comments', 'commentmodel');
31
+        \OCP\Util::addScript('comments', 'commentcollection');
32
+        \OCP\Util::addScript('comments', 'commentsummarymodel');
33
+        \OCP\Util::addScript('comments', 'commentstabview');
34
+        \OCP\Util::addScript('comments', 'filesplugin');
35
+        \OCP\Util::addScript('comments', 'activitytabviewplugin');
36
+        \OCP\Util::addStyle('comments', 'comments');
37
+    }
38 38
 );
39 39
 
40 40
 $eventDispatcher->addListener(\OCP\Comments\CommentsEntityEvent::EVENT_ENTITY, function(\OCP\Comments\CommentsEntityEvent $event) {
41
-	$event->addEntityCollection('files', function($name) {
42
-		$nodes = \OC::$server->getUserFolder()->getById(intval($name));
43
-		return !empty($nodes);
44
-	});
41
+    $event->addEntityCollection('files', function($name) {
42
+        $nodes = \OC::$server->getUserFolder()->getById(intval($name));
43
+        return !empty($nodes);
44
+    });
45 45
 });
46 46
 
47 47
 $notificationManager = \OC::$server->getNotificationManager();
48 48
 $notificationManager->registerNotifier(
49
-	function() {
50
-		$application = new \OCP\AppFramework\App('comments');
51
-		return $application->getContainer()->query(\OCA\Comments\Notification\Notifier::class);
52
-	},
53
-	function () {
54
-		$l = \OC::$server->getL10N('comments');
55
-		return ['id' => 'comments', 'name' => $l->t('Comments')];
56
-	}
49
+    function() {
50
+        $application = new \OCP\AppFramework\App('comments');
51
+        return $application->getContainer()->query(\OCA\Comments\Notification\Notifier::class);
52
+    },
53
+    function () {
54
+        $l = \OC::$server->getL10N('comments');
55
+        return ['id' => 'comments', 'name' => $l->t('Comments')];
56
+    }
57 57
 );
58 58
 
59 59
 $commentsManager = \OC::$server->getCommentsManager();
60 60
 $commentsManager->registerEventHandler(function () {
61
-	$application = new \OCP\AppFramework\App('comments');
62
-	/** @var \OCA\Comments\EventHandler $handler */
63
-	$handler = $application->getContainer()->query(\OCA\Comments\EventHandler::class);
64
-	return $handler;
61
+    $application = new \OCP\AppFramework\App('comments');
62
+    /** @var \OCA\Comments\EventHandler $handler */
63
+    $handler = $application->getContainer()->query(\OCA\Comments\EventHandler::class);
64
+    return $handler;
65 65
 });
66 66
 $commentsManager->registerDisplayNameResolver('user', function($id) {
67
-	$manager = \OC::$server->getUserManager();
68
-	$user = $manager->get($id);
69
-	if(is_null($user)) {
70
-		$l = \OC::$server->getL10N('comments');
71
-		$displayName = $l->t('Unknown user');
72
-	} else {
73
-		$displayName = $user->getDisplayName();
74
-	}
75
-	return $displayName;
67
+    $manager = \OC::$server->getUserManager();
68
+    $user = $manager->get($id);
69
+    if(is_null($user)) {
70
+        $l = \OC::$server->getL10N('comments');
71
+        $displayName = $l->t('Unknown user');
72
+    } else {
73
+        $displayName = $user->getDisplayName();
74
+    }
75
+    return $displayName;
76 76
 });
Please login to merge, or discard this patch.
apps/files_trashbin/ajax/undelete.php 1 patch
Indentation   +43 added lines, -43 removed lines patch added patch discarded remove patch
@@ -31,25 +31,25 @@  discard block
 block discarded – undo
31 31
 
32 32
 $dir = '/';
33 33
 if (isset($_POST['dir'])) {
34
-	$dir = rtrim((string)$_POST['dir'], '/'). '/';
34
+    $dir = rtrim((string)$_POST['dir'], '/'). '/';
35 35
 }
36 36
 $allFiles = false;
37 37
 if (isset($_POST['allfiles']) && (string)$_POST['allfiles'] === 'true') {
38
-	$allFiles = true;
39
-	$list = array();
40
-	$dirListing = true;
41
-	if ($dir === '' || $dir === '/') {
42
-		$dirListing = false;
43
-	}
44
-	foreach (OCA\Files_Trashbin\Helper::getTrashFiles($dir, \OCP\User::getUser()) as $file) {
45
-		$fileName = $file['name'];
46
-		if (!$dirListing) {
47
-			$fileName .= '.d' . $file['mtime'];
48
-		}
49
-		$list[] = $fileName;
50
-	}
38
+    $allFiles = true;
39
+    $list = array();
40
+    $dirListing = true;
41
+    if ($dir === '' || $dir === '/') {
42
+        $dirListing = false;
43
+    }
44
+    foreach (OCA\Files_Trashbin\Helper::getTrashFiles($dir, \OCP\User::getUser()) as $file) {
45
+        $fileName = $file['name'];
46
+        if (!$dirListing) {
47
+            $fileName .= '.d' . $file['mtime'];
48
+        }
49
+        $list[] = $fileName;
50
+    }
51 51
 } else {
52
-	$list = json_decode($_POST['files']);
52
+    $list = json_decode($_POST['files']);
53 53
 }
54 54
 
55 55
 $error = array();
@@ -57,38 +57,38 @@  discard block
 block discarded – undo
57 57
 
58 58
 $i = 0;
59 59
 foreach ($list as $file) {
60
-	$path = $dir . '/' . $file;
61
-	if ($dir === '/') {
62
-		$file = ltrim($file, '/');
63
-		$delimiter = strrpos($file, '.d');
64
-		$filename = substr($file, 0, $delimiter);
65
-		$timestamp =  substr($file, $delimiter+2);
66
-	} else {
67
-		$path_parts = pathinfo($file);
68
-		$filename = $path_parts['basename'];
69
-		$timestamp = null;
70
-	}
60
+    $path = $dir . '/' . $file;
61
+    if ($dir === '/') {
62
+        $file = ltrim($file, '/');
63
+        $delimiter = strrpos($file, '.d');
64
+        $filename = substr($file, 0, $delimiter);
65
+        $timestamp =  substr($file, $delimiter+2);
66
+    } else {
67
+        $path_parts = pathinfo($file);
68
+        $filename = $path_parts['basename'];
69
+        $timestamp = null;
70
+    }
71 71
 
72
-	if ( !OCA\Files_Trashbin\Trashbin::restore($path, $filename, $timestamp) ) {
73
-		$error[] = $filename;
74
-		\OCP\Util::writeLog('trashbin', 'can\'t restore ' . $filename, \OCP\Util::ERROR);
75
-	} else {
76
-		$success[$i]['filename'] = $file;
77
-		$success[$i]['timestamp'] = $timestamp;
78
-		$i++;
79
-	}
72
+    if ( !OCA\Files_Trashbin\Trashbin::restore($path, $filename, $timestamp) ) {
73
+        $error[] = $filename;
74
+        \OCP\Util::writeLog('trashbin', 'can\'t restore ' . $filename, \OCP\Util::ERROR);
75
+    } else {
76
+        $success[$i]['filename'] = $file;
77
+        $success[$i]['timestamp'] = $timestamp;
78
+        $i++;
79
+    }
80 80
 
81 81
 }
82 82
 
83 83
 if ( $error ) {
84
-	$filelist = '';
85
-	foreach ( $error as $e ) {
86
-		$filelist .= $e.', ';
87
-	}
88
-	$l = OC::$server->getL10N('files_trashbin');
89
-	$message = $l->t("Couldn't restore %s", array(rtrim($filelist, ', ')));
90
-	OCP\JSON::error(array("data" => array("message" => $message,
91
-										  "success" => $success, "error" => $error)));
84
+    $filelist = '';
85
+    foreach ( $error as $e ) {
86
+        $filelist .= $e.', ';
87
+    }
88
+    $l = OC::$server->getL10N('files_trashbin');
89
+    $message = $l->t("Couldn't restore %s", array(rtrim($filelist, ', ')));
90
+    OCP\JSON::error(array("data" => array("message" => $message,
91
+                                            "success" => $success, "error" => $error)));
92 92
 } else {
93
-	OCP\JSON::success(array("data" => array("success" => $success)));
93
+    OCP\JSON::success(array("data" => array("success" => $success)));
94 94
 }
Please login to merge, or discard this patch.
apps/files_trashbin/ajax/list.php 1 patch
Indentation   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -32,10 +32,10 @@
 block discarded – undo
32 32
 
33 33
 // make filelist
34 34
 try {
35
-	$files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir, \OCP\User::getUser(), $sortAttribute, $sortDirection);
35
+    $files = \OCA\Files_Trashbin\Helper::getTrashFiles($dir, \OCP\User::getUser(), $sortAttribute, $sortDirection);
36 36
 } catch (Exception $e) {
37
-	header("HTTP/1.0 404 Not Found");
38
-	exit();
37
+    header("HTTP/1.0 404 Not Found");
38
+    exit();
39 39
 }
40 40
 
41 41
 $encodedDir = \OCP\Util::encodePath($dir);
Please login to merge, or discard this patch.
apps/files_trashbin/ajax/delete.php 1 patch
Indentation   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -32,19 +32,19 @@  discard block
 block discarded – undo
32 32
 
33 33
 // "empty trash" command
34 34
 if (isset($_POST['allfiles']) && (string)$_POST['allfiles'] === 'true'){
35
-	$deleteAll = true;
36
-	if ($folder === '/' || $folder === '') {
37
-		OCA\Files_Trashbin\Trashbin::deleteAll();
38
-		$list = array();
39
-	} else {
40
-		$list[] = $folder;
41
-		$folder = dirname($folder);
42
-	}
35
+    $deleteAll = true;
36
+    if ($folder === '/' || $folder === '') {
37
+        OCA\Files_Trashbin\Trashbin::deleteAll();
38
+        $list = array();
39
+    } else {
40
+        $list[] = $folder;
41
+        $folder = dirname($folder);
42
+    }
43 43
 }
44 44
 else {
45
-	$deleteAll = false;
46
-	$files = (string)$_POST['files'];
47
-	$list = json_decode($files);
45
+    $deleteAll = false;
46
+    $files = (string)$_POST['files'];
47
+    $list = json_decode($files);
48 48
 }
49 49
 
50 50
 $folder = rtrim($folder, '/') . '/';
@@ -53,38 +53,38 @@  discard block
 block discarded – undo
53 53
 
54 54
 $i = 0;
55 55
 foreach ($list as $file) {
56
-	if ($folder === '/') {
57
-		$file = ltrim($file, '/');
58
-		$delimiter = strrpos($file, '.d');
59
-		$filename = substr($file, 0, $delimiter);
60
-		$timestamp =  substr($file, $delimiter+2);
61
-	} else {
62
-		$filename = $folder . '/' . $file;
63
-		$timestamp = null;
64
-	}
56
+    if ($folder === '/') {
57
+        $file = ltrim($file, '/');
58
+        $delimiter = strrpos($file, '.d');
59
+        $filename = substr($file, 0, $delimiter);
60
+        $timestamp =  substr($file, $delimiter+2);
61
+    } else {
62
+        $filename = $folder . '/' . $file;
63
+        $timestamp = null;
64
+    }
65 65
 
66
-	OCA\Files_Trashbin\Trashbin::delete($filename, \OCP\User::getUser(), $timestamp);
67
-	if (OCA\Files_Trashbin\Trashbin::file_exists($filename, $timestamp)) {
68
-		$error[] = $filename;
69
-		\OCP\Util::writeLog('trashbin','can\'t delete ' . $filename . ' permanently.', \OCP\Util::ERROR);
70
-	}
71
-	// only list deleted files if not deleting everything
72
-	else if (!$deleteAll) {
73
-		$success[$i]['filename'] = $file;
74
-		$success[$i]['timestamp'] = $timestamp;
75
-		$i++;
76
-	}
66
+    OCA\Files_Trashbin\Trashbin::delete($filename, \OCP\User::getUser(), $timestamp);
67
+    if (OCA\Files_Trashbin\Trashbin::file_exists($filename, $timestamp)) {
68
+        $error[] = $filename;
69
+        \OCP\Util::writeLog('trashbin','can\'t delete ' . $filename . ' permanently.', \OCP\Util::ERROR);
70
+    }
71
+    // only list deleted files if not deleting everything
72
+    else if (!$deleteAll) {
73
+        $success[$i]['filename'] = $file;
74
+        $success[$i]['timestamp'] = $timestamp;
75
+        $i++;
76
+    }
77 77
 }
78 78
 
79 79
 if ( $error ) {
80
-	$filelist = '';
81
-	foreach ( $error as $e ) {
82
-		$filelist .= $e.', ';
83
-	}
84
-	$l = \OC::$server->getL10N('files_trashbin');
85
-	$message = $l->t("Couldn't delete %s permanently", array(rtrim($filelist, ', ')));
86
-	OCP\JSON::error(array("data" => array("message" => $message,
87
-			                               "success" => $success, "error" => $error)));
80
+    $filelist = '';
81
+    foreach ( $error as $e ) {
82
+        $filelist .= $e.', ';
83
+    }
84
+    $l = \OC::$server->getL10N('files_trashbin');
85
+    $message = $l->t("Couldn't delete %s permanently", array(rtrim($filelist, ', ')));
86
+    OCP\JSON::error(array("data" => array("message" => $message,
87
+                                            "success" => $success, "error" => $error)));
88 88
 } else {
89
-	OCP\JSON::success(array("data" => array("success" => $success)));
89
+    OCP\JSON::success(array("data" => array("success" => $success)));
90 90
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Storage.php 1 patch
Indentation   +197 added lines, -197 removed lines patch added patch discarded remove patch
@@ -32,228 +32,228 @@
 block discarded – undo
32 32
 
33 33
 class Storage extends Wrapper {
34 34
 
35
-	private $mountPoint;
36
-	// remember already deleted files to avoid infinite loops if the trash bin
37
-	// move files across storages
38
-	private $deletedFiles = array();
35
+    private $mountPoint;
36
+    // remember already deleted files to avoid infinite loops if the trash bin
37
+    // move files across storages
38
+    private $deletedFiles = array();
39 39
 
40
-	/**
41
-	 * Disable trash logic
42
-	 *
43
-	 * @var bool
44
-	 */
45
-	private static $disableTrash = false;
40
+    /**
41
+     * Disable trash logic
42
+     *
43
+     * @var bool
44
+     */
45
+    private static $disableTrash = false;
46 46
 
47
-	/**
48
-	 * remember which file/folder was moved out of s shared folder
49
-	 * in this case we want to add a copy to the owners trash bin
50
-	 *
51
-	 * @var array
52
-	 */
53
-	private static $moveOutOfSharedFolder = [];
47
+    /**
48
+     * remember which file/folder was moved out of s shared folder
49
+     * in this case we want to add a copy to the owners trash bin
50
+     *
51
+     * @var array
52
+     */
53
+    private static $moveOutOfSharedFolder = [];
54 54
 
55
-	/** @var  IUserManager */
56
-	private $userManager;
55
+    /** @var  IUserManager */
56
+    private $userManager;
57 57
 
58
-	/**
59
-	 * Storage constructor.
60
-	 *
61
-	 * @param array $parameters
62
-	 * @param IUserManager|null $userManager
63
-	 */
64
-	public function __construct($parameters, IUserManager $userManager = null) {
65
-		$this->mountPoint = $parameters['mountPoint'];
66
-		$this->userManager = $userManager;
67
-		parent::__construct($parameters);
68
-	}
58
+    /**
59
+     * Storage constructor.
60
+     *
61
+     * @param array $parameters
62
+     * @param IUserManager|null $userManager
63
+     */
64
+    public function __construct($parameters, IUserManager $userManager = null) {
65
+        $this->mountPoint = $parameters['mountPoint'];
66
+        $this->userManager = $userManager;
67
+        parent::__construct($parameters);
68
+    }
69 69
 
70
-	/**
71
-	 * @internal
72
-	 */
73
-	public static function preRenameHook($params) {
74
-		// in cross-storage cases, a rename is a copy + unlink,
75
-		// that last unlink must not go to trash, only exception:
76
-		// if the file was moved from a shared storage to a local folder,
77
-		// in this case the owner should get a copy in his trash bin so that
78
-		// they can restore the files again
70
+    /**
71
+     * @internal
72
+     */
73
+    public static function preRenameHook($params) {
74
+        // in cross-storage cases, a rename is a copy + unlink,
75
+        // that last unlink must not go to trash, only exception:
76
+        // if the file was moved from a shared storage to a local folder,
77
+        // in this case the owner should get a copy in his trash bin so that
78
+        // they can restore the files again
79 79
 
80
-		$oldPath = $params['oldpath'];
81
-		$newPath = dirname($params['newpath']);
82
-		$currentUser = \OC::$server->getUserSession()->getUser();
80
+        $oldPath = $params['oldpath'];
81
+        $newPath = dirname($params['newpath']);
82
+        $currentUser = \OC::$server->getUserSession()->getUser();
83 83
 
84
-		$fileMovedOutOfSharedFolder = false;
84
+        $fileMovedOutOfSharedFolder = false;
85 85
 
86
-		try {
87
-			if ($currentUser) {
88
-				$currentUserId = $currentUser->getUID();
86
+        try {
87
+            if ($currentUser) {
88
+                $currentUserId = $currentUser->getUID();
89 89
 
90
-				$view = new View($currentUserId . '/files');
91
-				$fileInfo = $view->getFileInfo($oldPath);
92
-				if ($fileInfo) {
93
-					$sourceStorage = $fileInfo->getStorage();
94
-					$sourceOwner = $view->getOwner($oldPath);
95
-					$targetOwner = $view->getOwner($newPath);
90
+                $view = new View($currentUserId . '/files');
91
+                $fileInfo = $view->getFileInfo($oldPath);
92
+                if ($fileInfo) {
93
+                    $sourceStorage = $fileInfo->getStorage();
94
+                    $sourceOwner = $view->getOwner($oldPath);
95
+                    $targetOwner = $view->getOwner($newPath);
96 96
 
97
-					if ($sourceOwner !== $targetOwner
98
-						&& $sourceStorage->instanceOfStorage('OCA\Files_Sharing\SharedStorage')
99
-					) {
100
-						$fileMovedOutOfSharedFolder = true;
101
-					}
102
-				}
103
-			}
104
-		} catch (\Exception $e) {
105
-			// do nothing, in this case we just disable the trashbin and continue
106
-			$logger = \OC::$server->getLogger();
107
-			$logger->debug('Trashbin storage could not check if a file was moved out of a shared folder: ' . $e->getMessage());
108
-		}
97
+                    if ($sourceOwner !== $targetOwner
98
+                        && $sourceStorage->instanceOfStorage('OCA\Files_Sharing\SharedStorage')
99
+                    ) {
100
+                        $fileMovedOutOfSharedFolder = true;
101
+                    }
102
+                }
103
+            }
104
+        } catch (\Exception $e) {
105
+            // do nothing, in this case we just disable the trashbin and continue
106
+            $logger = \OC::$server->getLogger();
107
+            $logger->debug('Trashbin storage could not check if a file was moved out of a shared folder: ' . $e->getMessage());
108
+        }
109 109
 
110
-		if($fileMovedOutOfSharedFolder) {
111
-			self::$moveOutOfSharedFolder['/' . $currentUserId . '/files' . $oldPath] = true;
112
-		} else {
113
-			self::$disableTrash = true;
114
-		}
110
+        if($fileMovedOutOfSharedFolder) {
111
+            self::$moveOutOfSharedFolder['/' . $currentUserId . '/files' . $oldPath] = true;
112
+        } else {
113
+            self::$disableTrash = true;
114
+        }
115 115
 
116
-	}
116
+    }
117 117
 
118
-	/**
119
-	 * @internal
120
-	 */
121
-	public static function postRenameHook($params) {
122
-		self::$disableTrash = false;
123
-	}
118
+    /**
119
+     * @internal
120
+     */
121
+    public static function postRenameHook($params) {
122
+        self::$disableTrash = false;
123
+    }
124 124
 
125
-	/**
126
-	 * Rename path1 to path2 by calling the wrapped storage.
127
-	 *
128
-	 * @param string $path1 first path
129
-	 * @param string $path2 second path
130
-	 * @return bool
131
-	 */
132
-	public function rename($path1, $path2) {
133
-		$result = $this->storage->rename($path1, $path2);
134
-		if ($result === false) {
135
-			// when rename failed, the post_rename hook isn't triggered,
136
-			// but we still want to reenable the trash logic
137
-			self::$disableTrash = false;
138
-		}
139
-		return $result;
140
-	}
125
+    /**
126
+     * Rename path1 to path2 by calling the wrapped storage.
127
+     *
128
+     * @param string $path1 first path
129
+     * @param string $path2 second path
130
+     * @return bool
131
+     */
132
+    public function rename($path1, $path2) {
133
+        $result = $this->storage->rename($path1, $path2);
134
+        if ($result === false) {
135
+            // when rename failed, the post_rename hook isn't triggered,
136
+            // but we still want to reenable the trash logic
137
+            self::$disableTrash = false;
138
+        }
139
+        return $result;
140
+    }
141 141
 
142
-	/**
143
-	 * Deletes the given file by moving it into the trashbin.
144
-	 *
145
-	 * @param string $path path of file or folder to delete
146
-	 *
147
-	 * @return bool true if the operation succeeded, false otherwise
148
-	 */
149
-	public function unlink($path) {
150
-		if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
151
-			$result = $this->doDelete($path, 'unlink', true);
152
-			unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
153
-		} else {
154
-			$result = $this->doDelete($path, 'unlink');
155
-		}
142
+    /**
143
+     * Deletes the given file by moving it into the trashbin.
144
+     *
145
+     * @param string $path path of file or folder to delete
146
+     *
147
+     * @return bool true if the operation succeeded, false otherwise
148
+     */
149
+    public function unlink($path) {
150
+        if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
151
+            $result = $this->doDelete($path, 'unlink', true);
152
+            unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
153
+        } else {
154
+            $result = $this->doDelete($path, 'unlink');
155
+        }
156 156
 
157
-		return $result;
158
-	}
157
+        return $result;
158
+    }
159 159
 
160
-	/**
161
-	 * Deletes the given folder by moving it into the trashbin.
162
-	 *
163
-	 * @param string $path path of folder to delete
164
-	 *
165
-	 * @return bool true if the operation succeeded, false otherwise
166
-	 */
167
-	public function rmdir($path) {
168
-		if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
169
-			$result = $this->doDelete($path, 'rmdir', true);
170
-			unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
171
-		} else {
172
-			$result = $this->doDelete($path, 'rmdir');
173
-		}
160
+    /**
161
+     * Deletes the given folder by moving it into the trashbin.
162
+     *
163
+     * @param string $path path of folder to delete
164
+     *
165
+     * @return bool true if the operation succeeded, false otherwise
166
+     */
167
+    public function rmdir($path) {
168
+        if (isset(self::$moveOutOfSharedFolder[$this->mountPoint . $path])) {
169
+            $result = $this->doDelete($path, 'rmdir', true);
170
+            unset(self::$moveOutOfSharedFolder[$this->mountPoint . $path]);
171
+        } else {
172
+            $result = $this->doDelete($path, 'rmdir');
173
+        }
174 174
 
175
-		return $result;
176
-	}
175
+        return $result;
176
+    }
177 177
 
178
-	/**
179
-	 * check if it is a file located in data/user/files only files in the
180
-	 * 'files' directory should be moved to the trash
181
-	 *
182
-	 * @param $path
183
-	 * @return bool
184
-	 */
185
-	protected function shouldMoveToTrash($path){
186
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
187
-		$parts = explode('/', $normalized);
188
-		if (count($parts) < 4) {
189
-			return false;
190
-		}
178
+    /**
179
+     * check if it is a file located in data/user/files only files in the
180
+     * 'files' directory should be moved to the trash
181
+     *
182
+     * @param $path
183
+     * @return bool
184
+     */
185
+    protected function shouldMoveToTrash($path){
186
+        $normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path);
187
+        $parts = explode('/', $normalized);
188
+        if (count($parts) < 4) {
189
+            return false;
190
+        }
191 191
 
192
-		if ($this->userManager->userExists($parts[1]) && $parts[2] == 'files') {
193
-			return true;
194
-		}
192
+        if ($this->userManager->userExists($parts[1]) && $parts[2] == 'files') {
193
+            return true;
194
+        }
195 195
 
196
-		return false;
197
-	}
196
+        return false;
197
+    }
198 198
 
199
-	/**
200
-	 * Run the delete operation with the given method
201
-	 *
202
-	 * @param string $path path of file or folder to delete
203
-	 * @param string $method either "unlink" or "rmdir"
204
-	 * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
205
-	 *
206
-	 * @return bool true if the operation succeeded, false otherwise
207
-	 */
208
-	private function doDelete($path, $method, $ownerOnly = false) {
209
-		if (self::$disableTrash
210
-			|| !\OC_App::isEnabled('files_trashbin')
211
-			|| (pathinfo($path, PATHINFO_EXTENSION) === 'part')
212
-			|| $this->shouldMoveToTrash($path) === false
213
-		) {
214
-			return call_user_func_array([$this->storage, $method], [$path]);
215
-		}
199
+    /**
200
+     * Run the delete operation with the given method
201
+     *
202
+     * @param string $path path of file or folder to delete
203
+     * @param string $method either "unlink" or "rmdir"
204
+     * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
205
+     *
206
+     * @return bool true if the operation succeeded, false otherwise
207
+     */
208
+    private function doDelete($path, $method, $ownerOnly = false) {
209
+        if (self::$disableTrash
210
+            || !\OC_App::isEnabled('files_trashbin')
211
+            || (pathinfo($path, PATHINFO_EXTENSION) === 'part')
212
+            || $this->shouldMoveToTrash($path) === false
213
+        ) {
214
+            return call_user_func_array([$this->storage, $method], [$path]);
215
+        }
216 216
 
217
-		// check permissions before we continue, this is especially important for
218
-		// shared files
219
-		if (!$this->isDeletable($path)) {
220
-			return false;
221
-		}
217
+        // check permissions before we continue, this is especially important for
218
+        // shared files
219
+        if (!$this->isDeletable($path)) {
220
+            return false;
221
+        }
222 222
 
223
-		$normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path, true, false, true);
224
-		$result = true;
225
-		$view = Filesystem::getView();
226
-		if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
227
-			$this->deletedFiles[$normalized] = $normalized;
228
-			if ($filesPath = $view->getRelativePath($normalized)) {
229
-				$filesPath = trim($filesPath, '/');
230
-				$result = \OCA\Files_Trashbin\Trashbin::move2trash($filesPath, $ownerOnly);
231
-				// in cross-storage cases the file will be copied
232
-				// but not deleted, so we delete it here
233
-				if ($result) {
234
-					call_user_func_array([$this->storage, $method], [$path]);
235
-				}
236
-			} else {
237
-				$result = call_user_func_array([$this->storage, $method], [$path]);
238
-			}
239
-			unset($this->deletedFiles[$normalized]);
240
-		} else if ($this->storage->file_exists($path)) {
241
-			$result = call_user_func_array([$this->storage, $method], [$path]);
242
-		}
223
+        $normalized = Filesystem::normalizePath($this->mountPoint . '/' . $path, true, false, true);
224
+        $result = true;
225
+        $view = Filesystem::getView();
226
+        if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
227
+            $this->deletedFiles[$normalized] = $normalized;
228
+            if ($filesPath = $view->getRelativePath($normalized)) {
229
+                $filesPath = trim($filesPath, '/');
230
+                $result = \OCA\Files_Trashbin\Trashbin::move2trash($filesPath, $ownerOnly);
231
+                // in cross-storage cases the file will be copied
232
+                // but not deleted, so we delete it here
233
+                if ($result) {
234
+                    call_user_func_array([$this->storage, $method], [$path]);
235
+                }
236
+            } else {
237
+                $result = call_user_func_array([$this->storage, $method], [$path]);
238
+            }
239
+            unset($this->deletedFiles[$normalized]);
240
+        } else if ($this->storage->file_exists($path)) {
241
+            $result = call_user_func_array([$this->storage, $method], [$path]);
242
+        }
243 243
 
244
-		return $result;
245
-	}
244
+        return $result;
245
+    }
246 246
 
247
-	/**
248
-	 * Setup the storate wrapper callback
249
-	 */
250
-	public static function setupStorage() {
251
-		\OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
252
-			return new \OCA\Files_Trashbin\Storage(
253
-				array('storage' => $storage, 'mountPoint' => $mountPoint),
254
-				\OC::$server->getUserManager()
255
-			);
256
-		}, 1);
257
-	}
247
+    /**
248
+     * Setup the storate wrapper callback
249
+     */
250
+    public static function setupStorage() {
251
+        \OC\Files\Filesystem::addStorageWrapper('oc_trashbin', function ($mountPoint, $storage) {
252
+            return new \OCA\Files_Trashbin\Storage(
253
+                array('storage' => $storage, 'mountPoint' => $mountPoint),
254
+                \OC::$server->getUserManager()
255
+            );
256
+        }, 1);
257
+    }
258 258
 
259 259
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Trashbin.php 1 patch
Indentation   +933 added lines, -933 removed lines patch added patch discarded remove patch
@@ -47,937 +47,937 @@
 block discarded – undo
47 47
 
48 48
 class Trashbin {
49 49
 
50
-	// unit: percentage; 50% of available disk space/quota
51
-	const DEFAULTMAXSIZE = 50;
52
-
53
-	/**
54
-	 * Whether versions have already be rescanned during this PHP request
55
-	 *
56
-	 * @var bool
57
-	 */
58
-	private static $scannedVersions = false;
59
-
60
-	/**
61
-	 * Ensure we don't need to scan the file during the move to trash
62
-	 * by triggering the scan in the pre-hook
63
-	 *
64
-	 * @param array $params
65
-	 */
66
-	public static function ensureFileScannedHook($params) {
67
-		try {
68
-			self::getUidAndFilename($params['path']);
69
-		} catch (NotFoundException $e) {
70
-			// nothing to scan for non existing files
71
-		}
72
-	}
73
-
74
-	/**
75
-	 * get the UID of the owner of the file and the path to the file relative to
76
-	 * owners files folder
77
-	 *
78
-	 * @param string $filename
79
-	 * @return array
80
-	 * @throws \OC\User\NoUserException
81
-	 */
82
-	public static function getUidAndFilename($filename) {
83
-		$uid = Filesystem::getOwner($filename);
84
-		$userManager = \OC::$server->getUserManager();
85
-		// if the user with the UID doesn't exists, e.g. because the UID points
86
-		// to a remote user with a federated cloud ID we use the current logged-in
87
-		// user. We need a valid local user to move the file to the right trash bin
88
-		if (!$userManager->userExists($uid)) {
89
-			$uid = User::getUser();
90
-		}
91
-		if (!$uid) {
92
-			// no owner, usually because of share link from ext storage
93
-			return [null, null];
94
-		}
95
-		Filesystem::initMountPoints($uid);
96
-		if ($uid != User::getUser()) {
97
-			$info = Filesystem::getFileInfo($filename);
98
-			$ownerView = new View('/' . $uid . '/files');
99
-			try {
100
-				$filename = $ownerView->getPath($info['fileid']);
101
-			} catch (NotFoundException $e) {
102
-				$filename = null;
103
-			}
104
-		}
105
-		return [$uid, $filename];
106
-	}
107
-
108
-	/**
109
-	 * get original location of files for user
110
-	 *
111
-	 * @param string $user
112
-	 * @return array (filename => array (timestamp => original location))
113
-	 */
114
-	public static function getLocations($user) {
115
-		$query = \OC_DB::prepare('SELECT `id`, `timestamp`, `location`'
116
-			. ' FROM `*PREFIX*files_trash` WHERE `user`=?');
117
-		$result = $query->execute(array($user));
118
-		$array = array();
119
-		while ($row = $result->fetchRow()) {
120
-			if (isset($array[$row['id']])) {
121
-				$array[$row['id']][$row['timestamp']] = $row['location'];
122
-			} else {
123
-				$array[$row['id']] = array($row['timestamp'] => $row['location']);
124
-			}
125
-		}
126
-		return $array;
127
-	}
128
-
129
-	/**
130
-	 * get original location of file
131
-	 *
132
-	 * @param string $user
133
-	 * @param string $filename
134
-	 * @param string $timestamp
135
-	 * @return string original location
136
-	 */
137
-	public static function getLocation($user, $filename, $timestamp) {
138
-		$query = \OC_DB::prepare('SELECT `location` FROM `*PREFIX*files_trash`'
139
-			. ' WHERE `user`=? AND `id`=? AND `timestamp`=?');
140
-		$result = $query->execute(array($user, $filename, $timestamp))->fetchAll();
141
-		if (isset($result[0]['location'])) {
142
-			return $result[0]['location'];
143
-		} else {
144
-			return false;
145
-		}
146
-	}
147
-
148
-	private static function setUpTrash($user) {
149
-		$view = new View('/' . $user);
150
-		if (!$view->is_dir('files_trashbin')) {
151
-			$view->mkdir('files_trashbin');
152
-		}
153
-		if (!$view->is_dir('files_trashbin/files')) {
154
-			$view->mkdir('files_trashbin/files');
155
-		}
156
-		if (!$view->is_dir('files_trashbin/versions')) {
157
-			$view->mkdir('files_trashbin/versions');
158
-		}
159
-		if (!$view->is_dir('files_trashbin/keys')) {
160
-			$view->mkdir('files_trashbin/keys');
161
-		}
162
-	}
163
-
164
-
165
-	/**
166
-	 * copy file to owners trash
167
-	 *
168
-	 * @param string $sourcePath
169
-	 * @param string $owner
170
-	 * @param string $targetPath
171
-	 * @param $user
172
-	 * @param integer $timestamp
173
-	 */
174
-	private static function copyFilesToUser($sourcePath, $owner, $targetPath, $user, $timestamp) {
175
-		self::setUpTrash($owner);
176
-
177
-		$targetFilename = basename($targetPath);
178
-		$targetLocation = dirname($targetPath);
179
-
180
-		$sourceFilename = basename($sourcePath);
181
-
182
-		$view = new View('/');
183
-
184
-		$target = $user . '/files_trashbin/files/' . $targetFilename . '.d' . $timestamp;
185
-		$source = $owner . '/files_trashbin/files/' . $sourceFilename . '.d' . $timestamp;
186
-		self::copy_recursive($source, $target, $view);
187
-
188
-
189
-		if ($view->file_exists($target)) {
190
-			$query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
191
-			$result = $query->execute(array($targetFilename, $timestamp, $targetLocation, $user));
192
-			if (!$result) {
193
-				\OCP\Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated for the files owner', \OCP\Util::ERROR);
194
-			}
195
-		}
196
-	}
197
-
198
-
199
-	/**
200
-	 * move file to the trash bin
201
-	 *
202
-	 * @param string $file_path path to the deleted file/directory relative to the files root directory
203
-	 * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
204
-	 *
205
-	 * @return bool
206
-	 */
207
-	public static function move2trash($file_path, $ownerOnly = false) {
208
-		// get the user for which the filesystem is setup
209
-		$root = Filesystem::getRoot();
210
-		list(, $user) = explode('/', $root);
211
-		list($owner, $ownerPath) = self::getUidAndFilename($file_path);
212
-
213
-		// if no owner found (ex: ext storage + share link), will use the current user's trashbin then
214
-		if (is_null($owner)) {
215
-			$owner = $user;
216
-			$ownerPath = $file_path;
217
-		}
218
-
219
-		$ownerView = new View('/' . $owner);
220
-		// file has been deleted in between
221
-		if (is_null($ownerPath) || $ownerPath === '' || !$ownerView->file_exists('/files/' . $ownerPath)) {
222
-			return true;
223
-		}
224
-
225
-		self::setUpTrash($user);
226
-		if ($owner !== $user) {
227
-			// also setup for owner
228
-			self::setUpTrash($owner);
229
-		}
230
-
231
-		$path_parts = pathinfo($ownerPath);
232
-
233
-		$filename = $path_parts['basename'];
234
-		$location = $path_parts['dirname'];
235
-		$timestamp = time();
236
-
237
-		// disable proxy to prevent recursive calls
238
-		$trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp;
239
-
240
-		/** @var \OC\Files\Storage\Storage $trashStorage */
241
-		list($trashStorage, $trashInternalPath) = $ownerView->resolvePath($trashPath);
242
-		/** @var \OC\Files\Storage\Storage $sourceStorage */
243
-		list($sourceStorage, $sourceInternalPath) = $ownerView->resolvePath('/files/' . $ownerPath);
244
-		try {
245
-			$moveSuccessful = true;
246
-			if ($trashStorage->file_exists($trashInternalPath)) {
247
-				$trashStorage->unlink($trashInternalPath);
248
-			}
249
-			$trashStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
250
-		} catch (\OCA\Files_Trashbin\Exceptions\CopyRecursiveException $e) {
251
-			$moveSuccessful = false;
252
-			if ($trashStorage->file_exists($trashInternalPath)) {
253
-				$trashStorage->unlink($trashInternalPath);
254
-			}
255
-			\OCP\Util::writeLog('files_trashbin', 'Couldn\'t move ' . $file_path . ' to the trash bin', \OCP\Util::ERROR);
256
-		}
257
-
258
-		if ($sourceStorage->file_exists($sourceInternalPath)) { // failed to delete the original file, abort
259
-			$sourceStorage->unlink($sourceInternalPath);
260
-			return false;
261
-		}
262
-
263
-		$trashStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
264
-
265
-		if ($moveSuccessful) {
266
-			$query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
267
-			$result = $query->execute(array($filename, $timestamp, $location, $owner));
268
-			if (!$result) {
269
-				\OCP\Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated', \OCP\Util::ERROR);
270
-			}
271
-			\OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', array('filePath' => Filesystem::normalizePath($file_path),
272
-				'trashPath' => Filesystem::normalizePath($filename . '.d' . $timestamp)));
273
-
274
-			self::retainVersions($filename, $owner, $ownerPath, $timestamp);
275
-
276
-			// if owner !== user we need to also add a copy to the users trash
277
-			if ($user !== $owner && $ownerOnly === false) {
278
-				self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
279
-			}
280
-		}
281
-
282
-		self::scheduleExpire($user);
283
-
284
-		// if owner !== user we also need to update the owners trash size
285
-		if ($owner !== $user) {
286
-			self::scheduleExpire($owner);
287
-		}
288
-
289
-		return $moveSuccessful;
290
-	}
291
-
292
-	/**
293
-	 * Move file versions to trash so that they can be restored later
294
-	 *
295
-	 * @param string $filename of deleted file
296
-	 * @param string $owner owner user id
297
-	 * @param string $ownerPath path relative to the owner's home storage
298
-	 * @param integer $timestamp when the file was deleted
299
-	 */
300
-	private static function retainVersions($filename, $owner, $ownerPath, $timestamp) {
301
-		if (\OCP\App::isEnabled('files_versions') && !empty($ownerPath)) {
302
-
303
-			$user = User::getUser();
304
-			$rootView = new View('/');
305
-
306
-			if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) {
307
-				if ($owner !== $user) {
308
-					self::copy_recursive($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp, $rootView);
309
-				}
310
-				self::move($rootView, $owner . '/files_versions/' . $ownerPath, $user . '/files_trashbin/versions/' . $filename . '.d' . $timestamp);
311
-			} else if ($versions = \OCA\Files_Versions\Storage::getVersions($owner, $ownerPath)) {
312
-
313
-				foreach ($versions as $v) {
314
-					if ($owner !== $user) {
315
-						self::copy($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $owner . '/files_trashbin/versions/' . $v['name'] . '.v' . $v['version'] . '.d' . $timestamp);
316
-					}
317
-					self::move($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $user . '/files_trashbin/versions/' . $filename . '.v' . $v['version'] . '.d' . $timestamp);
318
-				}
319
-			}
320
-		}
321
-	}
322
-
323
-	/**
324
-	 * Move a file or folder on storage level
325
-	 *
326
-	 * @param View $view
327
-	 * @param string $source
328
-	 * @param string $target
329
-	 * @return bool
330
-	 */
331
-	private static function move(View $view, $source, $target) {
332
-		/** @var \OC\Files\Storage\Storage $sourceStorage */
333
-		list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
334
-		/** @var \OC\Files\Storage\Storage $targetStorage */
335
-		list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
336
-		/** @var \OC\Files\Storage\Storage $ownerTrashStorage */
337
-
338
-		$result = $targetStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
339
-		if ($result) {
340
-			$targetStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
341
-		}
342
-		return $result;
343
-	}
344
-
345
-	/**
346
-	 * Copy a file or folder on storage level
347
-	 *
348
-	 * @param View $view
349
-	 * @param string $source
350
-	 * @param string $target
351
-	 * @return bool
352
-	 */
353
-	private static function copy(View $view, $source, $target) {
354
-		/** @var \OC\Files\Storage\Storage $sourceStorage */
355
-		list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
356
-		/** @var \OC\Files\Storage\Storage $targetStorage */
357
-		list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
358
-		/** @var \OC\Files\Storage\Storage $ownerTrashStorage */
359
-
360
-		$result = $targetStorage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
361
-		if ($result) {
362
-			$targetStorage->getUpdater()->update($targetInternalPath);
363
-		}
364
-		return $result;
365
-	}
366
-
367
-	/**
368
-	 * Restore a file or folder from trash bin
369
-	 *
370
-	 * @param string $file path to the deleted file/folder relative to "files_trashbin/files/",
371
-	 * including the timestamp suffix ".d12345678"
372
-	 * @param string $filename name of the file/folder
373
-	 * @param int $timestamp time when the file/folder was deleted
374
-	 *
375
-	 * @return bool true on success, false otherwise
376
-	 */
377
-	public static function restore($file, $filename, $timestamp) {
378
-		$user = User::getUser();
379
-		$view = new View('/' . $user);
380
-
381
-		$location = '';
382
-		if ($timestamp) {
383
-			$location = self::getLocation($user, $filename, $timestamp);
384
-			if ($location === false) {
385
-				\OCP\Util::writeLog('files_trashbin', 'trash bin database inconsistent!', \OCP\Util::ERROR);
386
-			} else {
387
-				// if location no longer exists, restore file in the root directory
388
-				if ($location !== '/' &&
389
-					(!$view->is_dir('files/' . $location) ||
390
-						!$view->isCreatable('files/' . $location))
391
-				) {
392
-					$location = '';
393
-				}
394
-			}
395
-		}
396
-
397
-		// we need a  extension in case a file/dir with the same name already exists
398
-		$uniqueFilename = self::getUniqueFilename($location, $filename, $view);
399
-
400
-		$source = Filesystem::normalizePath('files_trashbin/files/' . $file);
401
-		$target = Filesystem::normalizePath('files/' . $location . '/' . $uniqueFilename);
402
-		if (!$view->file_exists($source)) {
403
-			return false;
404
-		}
405
-		$mtime = $view->filemtime($source);
406
-
407
-		// restore file
408
-		$restoreResult = $view->rename($source, $target);
409
-
410
-		// handle the restore result
411
-		if ($restoreResult) {
412
-			$fakeRoot = $view->getRoot();
413
-			$view->chroot('/' . $user . '/files');
414
-			$view->touch('/' . $location . '/' . $uniqueFilename, $mtime);
415
-			$view->chroot($fakeRoot);
416
-			\OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', array('filePath' => Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename),
417
-				'trashPath' => Filesystem::normalizePath($file)));
418
-
419
-			self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp);
420
-
421
-			if ($timestamp) {
422
-				$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
423
-				$query->execute(array($user, $filename, $timestamp));
424
-			}
425
-
426
-			return true;
427
-		}
428
-
429
-		return false;
430
-	}
431
-
432
-	/**
433
-	 * restore versions from trash bin
434
-	 *
435
-	 * @param View $view file view
436
-	 * @param string $file complete path to file
437
-	 * @param string $filename name of file once it was deleted
438
-	 * @param string $uniqueFilename new file name to restore the file without overwriting existing files
439
-	 * @param string $location location if file
440
-	 * @param int $timestamp deletion time
441
-	 * @return false|null
442
-	 */
443
-	private static function restoreVersions(View $view, $file, $filename, $uniqueFilename, $location, $timestamp) {
444
-
445
-		if (\OCP\App::isEnabled('files_versions')) {
446
-
447
-			$user = User::getUser();
448
-			$rootView = new View('/');
449
-
450
-			$target = Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename);
451
-
452
-			list($owner, $ownerPath) = self::getUidAndFilename($target);
453
-
454
-			// file has been deleted in between
455
-			if (empty($ownerPath)) {
456
-				return false;
457
-			}
458
-
459
-			if ($timestamp) {
460
-				$versionedFile = $filename;
461
-			} else {
462
-				$versionedFile = $file;
463
-			}
464
-
465
-			if ($view->is_dir('/files_trashbin/versions/' . $file)) {
466
-				$rootView->rename(Filesystem::normalizePath($user . '/files_trashbin/versions/' . $file), Filesystem::normalizePath($owner . '/files_versions/' . $ownerPath));
467
-			} else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp, $user)) {
468
-				foreach ($versions as $v) {
469
-					if ($timestamp) {
470
-						$rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
471
-					} else {
472
-						$rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
473
-					}
474
-				}
475
-			}
476
-		}
477
-	}
478
-
479
-	/**
480
-	 * delete all files from the trash
481
-	 */
482
-	public static function deleteAll() {
483
-		$user = User::getUser();
484
-		$view = new View('/' . $user);
485
-		$fileInfos = $view->getDirectoryContent('files_trashbin/files');
486
-
487
-		// Array to store the relative path in (after the file is deleted, the view won't be able to relativise the path anymore)
488
-		$filePaths = array();
489
-		foreach($fileInfos as $fileInfo){
490
-			$filePaths[] = $view->getRelativePath($fileInfo->getPath());
491
-		}
492
-		unset($fileInfos); // save memory
493
-
494
-		// Bulk PreDelete-Hook
495
-		\OC_Hook::emit('\OCP\Trashbin', 'preDeleteAll', array('paths' => $filePaths));
496
-
497
-		// Single-File Hooks
498
-		foreach($filePaths as $path){
499
-			self::emitTrashbinPreDelete($path);
500
-		}
501
-
502
-		// actual file deletion
503
-		$view->deleteAll('files_trashbin');
504
-		$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
505
-		$query->execute(array($user));
506
-
507
-		// Bulk PostDelete-Hook
508
-		\OC_Hook::emit('\OCP\Trashbin', 'deleteAll', array('paths' => $filePaths));
509
-
510
-		// Single-File Hooks
511
-		foreach($filePaths as $path){
512
-			self::emitTrashbinPostDelete($path);
513
-		}
514
-
515
-		$view->mkdir('files_trashbin');
516
-		$view->mkdir('files_trashbin/files');
517
-
518
-		return true;
519
-	}
520
-
521
-	/**
522
-	 * wrapper function to emit the 'preDelete' hook of \OCP\Trashbin before a file is deleted
523
-	 * @param string $path
524
-	 */
525
-	protected static function emitTrashbinPreDelete($path){
526
-		\OC_Hook::emit('\OCP\Trashbin', 'preDelete', array('path' => $path));
527
-	}
528
-
529
-	/**
530
-	 * wrapper function to emit the 'delete' hook of \OCP\Trashbin after a file has been deleted
531
-	 * @param string $path
532
-	 */
533
-	protected static function emitTrashbinPostDelete($path){
534
-		\OC_Hook::emit('\OCP\Trashbin', 'delete', array('path' => $path));
535
-	}
536
-
537
-	/**
538
-	 * delete file from trash bin permanently
539
-	 *
540
-	 * @param string $filename path to the file
541
-	 * @param string $user
542
-	 * @param int $timestamp of deletion time
543
-	 *
544
-	 * @return int size of deleted files
545
-	 */
546
-	public static function delete($filename, $user, $timestamp = null) {
547
-		$view = new View('/' . $user);
548
-		$size = 0;
549
-
550
-		if ($timestamp) {
551
-			$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
552
-			$query->execute(array($user, $filename, $timestamp));
553
-			$file = $filename . '.d' . $timestamp;
554
-		} else {
555
-			$file = $filename;
556
-		}
557
-
558
-		$size += self::deleteVersions($view, $file, $filename, $timestamp, $user);
559
-
560
-		if ($view->is_dir('/files_trashbin/files/' . $file)) {
561
-			$size += self::calculateSize(new View('/' . $user . '/files_trashbin/files/' . $file));
562
-		} else {
563
-			$size += $view->filesize('/files_trashbin/files/' . $file);
564
-		}
565
-		self::emitTrashbinPreDelete('/files_trashbin/files/' . $file);
566
-		$view->unlink('/files_trashbin/files/' . $file);
567
-		self::emitTrashbinPostDelete('/files_trashbin/files/' . $file);
568
-
569
-		return $size;
570
-	}
571
-
572
-	/**
573
-	 * @param View $view
574
-	 * @param string $file
575
-	 * @param string $filename
576
-	 * @param integer|null $timestamp
577
-	 * @param string $user
578
-	 * @return int
579
-	 */
580
-	private static function deleteVersions(View $view, $file, $filename, $timestamp, $user) {
581
-		$size = 0;
582
-		if (\OCP\App::isEnabled('files_versions')) {
583
-			if ($view->is_dir('files_trashbin/versions/' . $file)) {
584
-				$size += self::calculateSize(new View('/' . $user . '/files_trashbin/versions/' . $file));
585
-				$view->unlink('files_trashbin/versions/' . $file);
586
-			} else if ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) {
587
-				foreach ($versions as $v) {
588
-					if ($timestamp) {
589
-						$size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
590
-						$view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
591
-					} else {
592
-						$size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v);
593
-						$view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v);
594
-					}
595
-				}
596
-			}
597
-		}
598
-		return $size;
599
-	}
600
-
601
-	/**
602
-	 * check to see whether a file exists in trashbin
603
-	 *
604
-	 * @param string $filename path to the file
605
-	 * @param int $timestamp of deletion time
606
-	 * @return bool true if file exists, otherwise false
607
-	 */
608
-	public static function file_exists($filename, $timestamp = null) {
609
-		$user = User::getUser();
610
-		$view = new View('/' . $user);
611
-
612
-		if ($timestamp) {
613
-			$filename = $filename . '.d' . $timestamp;
614
-		} else {
615
-			$filename = $filename;
616
-		}
617
-
618
-		$target = Filesystem::normalizePath('files_trashbin/files/' . $filename);
619
-		return $view->file_exists($target);
620
-	}
621
-
622
-	/**
623
-	 * deletes used space for trash bin in db if user was deleted
624
-	 *
625
-	 * @param string $uid id of deleted user
626
-	 * @return bool result of db delete operation
627
-	 */
628
-	public static function deleteUser($uid) {
629
-		$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
630
-		return $query->execute(array($uid));
631
-	}
632
-
633
-	/**
634
-	 * calculate remaining free space for trash bin
635
-	 *
636
-	 * @param integer $trashbinSize current size of the trash bin
637
-	 * @param string $user
638
-	 * @return int available free space for trash bin
639
-	 */
640
-	private static function calculateFreeSpace($trashbinSize, $user) {
641
-		$softQuota = true;
642
-		$userObject = \OC::$server->getUserManager()->get($user);
643
-		if(is_null($userObject)) {
644
-			return 0;
645
-		}
646
-		$quota = $userObject->getQuota();
647
-		if ($quota === null || $quota === 'none') {
648
-			$quota = Filesystem::free_space('/');
649
-			$softQuota = false;
650
-			// inf or unknown free space
651
-			if ($quota < 0) {
652
-				$quota = PHP_INT_MAX;
653
-			}
654
-		} else {
655
-			$quota = \OCP\Util::computerFileSize($quota);
656
-		}
657
-
658
-		// calculate available space for trash bin
659
-		// subtract size of files and current trash bin size from quota
660
-		if ($softQuota) {
661
-			$userFolder = \OC::$server->getUserFolder($user);
662
-			if(is_null($userFolder)) {
663
-				return 0;
664
-			}
665
-			$free = $quota - $userFolder->getSize(); // remaining free space for user
666
-			if ($free > 0) {
667
-				$availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $trashbinSize; // how much space can be used for versions
668
-			} else {
669
-				$availableSpace = $free - $trashbinSize;
670
-			}
671
-		} else {
672
-			$availableSpace = $quota;
673
-		}
674
-
675
-		return $availableSpace;
676
-	}
677
-
678
-	/**
679
-	 * resize trash bin if necessary after a new file was added to ownCloud
680
-	 *
681
-	 * @param string $user user id
682
-	 */
683
-	public static function resizeTrash($user) {
684
-
685
-		$size = self::getTrashbinSize($user);
686
-
687
-		$freeSpace = self::calculateFreeSpace($size, $user);
688
-
689
-		if ($freeSpace < 0) {
690
-			self::scheduleExpire($user);
691
-		}
692
-	}
693
-
694
-	/**
695
-	 * clean up the trash bin
696
-	 *
697
-	 * @param string $user
698
-	 */
699
-	public static function expire($user) {
700
-		$trashBinSize = self::getTrashbinSize($user);
701
-		$availableSpace = self::calculateFreeSpace($trashBinSize, $user);
702
-
703
-		$dirContent = Helper::getTrashFiles('/', $user, 'mtime');
704
-
705
-		// delete all files older then $retention_obligation
706
-		list($delSize, $count) = self::deleteExpiredFiles($dirContent, $user);
707
-
708
-		$availableSpace += $delSize;
709
-
710
-		// delete files from trash until we meet the trash bin size limit again
711
-		self::deleteFiles(array_slice($dirContent, $count), $user, $availableSpace);
712
-	}
713
-
714
-	/**
715
-	 * @param string $user
716
-	 */
717
-	private static function scheduleExpire($user) {
718
-		// let the admin disable auto expire
719
-		$application = new Application();
720
-		$expiration = $application->getContainer()->query('Expiration');
721
-		if ($expiration->isEnabled()) {
722
-			\OC::$server->getCommandBus()->push(new Expire($user));
723
-		}
724
-	}
725
-
726
-	/**
727
-	 * if the size limit for the trash bin is reached, we delete the oldest
728
-	 * files in the trash bin until we meet the limit again
729
-	 *
730
-	 * @param array $files
731
-	 * @param string $user
732
-	 * @param int $availableSpace available disc space
733
-	 * @return int size of deleted files
734
-	 */
735
-	protected static function deleteFiles($files, $user, $availableSpace) {
736
-		$application = new Application();
737
-		$expiration = $application->getContainer()->query('Expiration');
738
-		$size = 0;
739
-
740
-		if ($availableSpace < 0) {
741
-			foreach ($files as $file) {
742
-				if ($availableSpace < 0 && $expiration->isExpired($file['mtime'], true)) {
743
-					$tmp = self::delete($file['name'], $user, $file['mtime']);
744
-					\OCP\Util::writeLog('files_trashbin', 'remove "' . $file['name'] . '" (' . $tmp . 'B) to meet the limit of trash bin size (50% of available quota)', \OCP\Util::INFO);
745
-					$availableSpace += $tmp;
746
-					$size += $tmp;
747
-				} else {
748
-					break;
749
-				}
750
-			}
751
-		}
752
-		return $size;
753
-	}
754
-
755
-	/**
756
-	 * delete files older then max storage time
757
-	 *
758
-	 * @param array $files list of files sorted by mtime
759
-	 * @param string $user
760
-	 * @return integer[] size of deleted files and number of deleted files
761
-	 */
762
-	public static function deleteExpiredFiles($files, $user) {
763
-		$application = new Application();
764
-		$expiration = $application->getContainer()->query('Expiration');
765
-		$size = 0;
766
-		$count = 0;
767
-		foreach ($files as $file) {
768
-			$timestamp = $file['mtime'];
769
-			$filename = $file['name'];
770
-			if ($expiration->isExpired($timestamp)) {
771
-				$count++;
772
-				$size += self::delete($filename, $user, $timestamp);
773
-				\OC::$server->getLogger()->info(
774
-					'Remove "' . $filename . '" from trashbin because it exceeds max retention obligation term.',
775
-					['app' => 'files_trashbin']
776
-				);
777
-			} else {
778
-				break;
779
-			}
780
-		}
781
-
782
-		return array($size, $count);
783
-	}
784
-
785
-	/**
786
-	 * recursive copy to copy a whole directory
787
-	 *
788
-	 * @param string $source source path, relative to the users files directory
789
-	 * @param string $destination destination path relative to the users root directoy
790
-	 * @param View $view file view for the users root directory
791
-	 * @return int
792
-	 * @throws Exceptions\CopyRecursiveException
793
-	 */
794
-	private static function copy_recursive($source, $destination, View $view) {
795
-		$size = 0;
796
-		if ($view->is_dir($source)) {
797
-			$view->mkdir($destination);
798
-			$view->touch($destination, $view->filemtime($source));
799
-			foreach ($view->getDirectoryContent($source) as $i) {
800
-				$pathDir = $source . '/' . $i['name'];
801
-				if ($view->is_dir($pathDir)) {
802
-					$size += self::copy_recursive($pathDir, $destination . '/' . $i['name'], $view);
803
-				} else {
804
-					$size += $view->filesize($pathDir);
805
-					$result = $view->copy($pathDir, $destination . '/' . $i['name']);
806
-					if (!$result) {
807
-						throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
808
-					}
809
-					$view->touch($destination . '/' . $i['name'], $view->filemtime($pathDir));
810
-				}
811
-			}
812
-		} else {
813
-			$size += $view->filesize($source);
814
-			$result = $view->copy($source, $destination);
815
-			if (!$result) {
816
-				throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
817
-			}
818
-			$view->touch($destination, $view->filemtime($source));
819
-		}
820
-		return $size;
821
-	}
822
-
823
-	/**
824
-	 * find all versions which belong to the file we want to restore
825
-	 *
826
-	 * @param string $filename name of the file which should be restored
827
-	 * @param int $timestamp timestamp when the file was deleted
828
-	 * @return array
829
-	 */
830
-	private static function getVersionsFromTrash($filename, $timestamp, $user) {
831
-		$view = new View('/' . $user . '/files_trashbin/versions');
832
-		$versions = array();
833
-
834
-		//force rescan of versions, local storage may not have updated the cache
835
-		if (!self::$scannedVersions) {
836
-			/** @var \OC\Files\Storage\Storage $storage */
837
-			list($storage,) = $view->resolvePath('/');
838
-			$storage->getScanner()->scan('files_trashbin/versions');
839
-			self::$scannedVersions = true;
840
-		}
841
-
842
-		if ($timestamp) {
843
-			// fetch for old versions
844
-			$matches = $view->searchRaw($filename . '.v%.d' . $timestamp);
845
-			$offset = -strlen($timestamp) - 2;
846
-		} else {
847
-			$matches = $view->searchRaw($filename . '.v%');
848
-		}
849
-
850
-		if (is_array($matches)) {
851
-			foreach ($matches as $ma) {
852
-				if ($timestamp) {
853
-					$parts = explode('.v', substr($ma['path'], 0, $offset));
854
-					$versions[] = (end($parts));
855
-				} else {
856
-					$parts = explode('.v', $ma);
857
-					$versions[] = (end($parts));
858
-				}
859
-			}
860
-		}
861
-		return $versions;
862
-	}
863
-
864
-	/**
865
-	 * find unique extension for restored file if a file with the same name already exists
866
-	 *
867
-	 * @param string $location where the file should be restored
868
-	 * @param string $filename name of the file
869
-	 * @param View $view filesystem view relative to users root directory
870
-	 * @return string with unique extension
871
-	 */
872
-	private static function getUniqueFilename($location, $filename, View $view) {
873
-		$ext = pathinfo($filename, PATHINFO_EXTENSION);
874
-		$name = pathinfo($filename, PATHINFO_FILENAME);
875
-		$l = \OC::$server->getL10N('files_trashbin');
876
-
877
-		$location = '/' . trim($location, '/');
878
-
879
-		// if extension is not empty we set a dot in front of it
880
-		if ($ext !== '') {
881
-			$ext = '.' . $ext;
882
-		}
883
-
884
-		if ($view->file_exists('files' . $location . '/' . $filename)) {
885
-			$i = 2;
886
-			$uniqueName = $name . " (" . $l->t("restored") . ")" . $ext;
887
-			while ($view->file_exists('files' . $location . '/' . $uniqueName)) {
888
-				$uniqueName = $name . " (" . $l->t("restored") . " " . $i . ")" . $ext;
889
-				$i++;
890
-			}
891
-
892
-			return $uniqueName;
893
-		}
894
-
895
-		return $filename;
896
-	}
897
-
898
-	/**
899
-	 * get the size from a given root folder
900
-	 *
901
-	 * @param View $view file view on the root folder
902
-	 * @return integer size of the folder
903
-	 */
904
-	private static function calculateSize($view) {
905
-		$root = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . $view->getAbsolutePath('');
906
-		if (!file_exists($root)) {
907
-			return 0;
908
-		}
909
-		$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($root), \RecursiveIteratorIterator::CHILD_FIRST);
910
-		$size = 0;
911
-
912
-		/**
913
-		 * RecursiveDirectoryIterator on an NFS path isn't iterable with foreach
914
-		 * This bug is fixed in PHP 5.5.9 or before
915
-		 * See #8376
916
-		 */
917
-		$iterator->rewind();
918
-		while ($iterator->valid()) {
919
-			$path = $iterator->current();
920
-			$relpath = substr($path, strlen($root) - 1);
921
-			if (!$view->is_dir($relpath)) {
922
-				$size += $view->filesize($relpath);
923
-			}
924
-			$iterator->next();
925
-		}
926
-		return $size;
927
-	}
928
-
929
-	/**
930
-	 * get current size of trash bin from a given user
931
-	 *
932
-	 * @param string $user user who owns the trash bin
933
-	 * @return integer trash bin size
934
-	 */
935
-	private static function getTrashbinSize($user) {
936
-		$view = new View('/' . $user);
937
-		$fileInfo = $view->getFileInfo('/files_trashbin');
938
-		return isset($fileInfo['size']) ? $fileInfo['size'] : 0;
939
-	}
940
-
941
-	/**
942
-	 * register hooks
943
-	 */
944
-	public static function registerHooks() {
945
-		// create storage wrapper on setup
946
-		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', 'OCA\Files_Trashbin\Storage', 'setupStorage');
947
-		//Listen to delete user signal
948
-		\OCP\Util::connectHook('OC_User', 'pre_deleteUser', 'OCA\Files_Trashbin\Hooks', 'deleteUser_hook');
949
-		//Listen to post write hook
950
-		\OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\Files_Trashbin\Hooks', 'post_write_hook');
951
-		// pre and post-rename, disable trash logic for the copy+unlink case
952
-		\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook');
953
-		\OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Files_Trashbin\Storage', 'preRenameHook');
954
-		\OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Files_Trashbin\Storage', 'postRenameHook');
955
-	}
956
-
957
-	/**
958
-	 * check if trash bin is empty for a given user
959
-	 *
960
-	 * @param string $user
961
-	 * @return bool
962
-	 */
963
-	public static function isEmpty($user) {
964
-
965
-		$view = new View('/' . $user . '/files_trashbin');
966
-		if ($view->is_dir('/files') && $dh = $view->opendir('/files')) {
967
-			while ($file = readdir($dh)) {
968
-				if (!Filesystem::isIgnoredDir($file)) {
969
-					return false;
970
-				}
971
-			}
972
-		}
973
-		return true;
974
-	}
975
-
976
-	/**
977
-	 * @param $path
978
-	 * @return string
979
-	 */
980
-	public static function preview_icon($path) {
981
-		return \OCP\Util::linkToRoute('core_ajax_trashbin_preview', array('x' => 32, 'y' => 32, 'file' => $path));
982
-	}
50
+    // unit: percentage; 50% of available disk space/quota
51
+    const DEFAULTMAXSIZE = 50;
52
+
53
+    /**
54
+     * Whether versions have already be rescanned during this PHP request
55
+     *
56
+     * @var bool
57
+     */
58
+    private static $scannedVersions = false;
59
+
60
+    /**
61
+     * Ensure we don't need to scan the file during the move to trash
62
+     * by triggering the scan in the pre-hook
63
+     *
64
+     * @param array $params
65
+     */
66
+    public static function ensureFileScannedHook($params) {
67
+        try {
68
+            self::getUidAndFilename($params['path']);
69
+        } catch (NotFoundException $e) {
70
+            // nothing to scan for non existing files
71
+        }
72
+    }
73
+
74
+    /**
75
+     * get the UID of the owner of the file and the path to the file relative to
76
+     * owners files folder
77
+     *
78
+     * @param string $filename
79
+     * @return array
80
+     * @throws \OC\User\NoUserException
81
+     */
82
+    public static function getUidAndFilename($filename) {
83
+        $uid = Filesystem::getOwner($filename);
84
+        $userManager = \OC::$server->getUserManager();
85
+        // if the user with the UID doesn't exists, e.g. because the UID points
86
+        // to a remote user with a federated cloud ID we use the current logged-in
87
+        // user. We need a valid local user to move the file to the right trash bin
88
+        if (!$userManager->userExists($uid)) {
89
+            $uid = User::getUser();
90
+        }
91
+        if (!$uid) {
92
+            // no owner, usually because of share link from ext storage
93
+            return [null, null];
94
+        }
95
+        Filesystem::initMountPoints($uid);
96
+        if ($uid != User::getUser()) {
97
+            $info = Filesystem::getFileInfo($filename);
98
+            $ownerView = new View('/' . $uid . '/files');
99
+            try {
100
+                $filename = $ownerView->getPath($info['fileid']);
101
+            } catch (NotFoundException $e) {
102
+                $filename = null;
103
+            }
104
+        }
105
+        return [$uid, $filename];
106
+    }
107
+
108
+    /**
109
+     * get original location of files for user
110
+     *
111
+     * @param string $user
112
+     * @return array (filename => array (timestamp => original location))
113
+     */
114
+    public static function getLocations($user) {
115
+        $query = \OC_DB::prepare('SELECT `id`, `timestamp`, `location`'
116
+            . ' FROM `*PREFIX*files_trash` WHERE `user`=?');
117
+        $result = $query->execute(array($user));
118
+        $array = array();
119
+        while ($row = $result->fetchRow()) {
120
+            if (isset($array[$row['id']])) {
121
+                $array[$row['id']][$row['timestamp']] = $row['location'];
122
+            } else {
123
+                $array[$row['id']] = array($row['timestamp'] => $row['location']);
124
+            }
125
+        }
126
+        return $array;
127
+    }
128
+
129
+    /**
130
+     * get original location of file
131
+     *
132
+     * @param string $user
133
+     * @param string $filename
134
+     * @param string $timestamp
135
+     * @return string original location
136
+     */
137
+    public static function getLocation($user, $filename, $timestamp) {
138
+        $query = \OC_DB::prepare('SELECT `location` FROM `*PREFIX*files_trash`'
139
+            . ' WHERE `user`=? AND `id`=? AND `timestamp`=?');
140
+        $result = $query->execute(array($user, $filename, $timestamp))->fetchAll();
141
+        if (isset($result[0]['location'])) {
142
+            return $result[0]['location'];
143
+        } else {
144
+            return false;
145
+        }
146
+    }
147
+
148
+    private static function setUpTrash($user) {
149
+        $view = new View('/' . $user);
150
+        if (!$view->is_dir('files_trashbin')) {
151
+            $view->mkdir('files_trashbin');
152
+        }
153
+        if (!$view->is_dir('files_trashbin/files')) {
154
+            $view->mkdir('files_trashbin/files');
155
+        }
156
+        if (!$view->is_dir('files_trashbin/versions')) {
157
+            $view->mkdir('files_trashbin/versions');
158
+        }
159
+        if (!$view->is_dir('files_trashbin/keys')) {
160
+            $view->mkdir('files_trashbin/keys');
161
+        }
162
+    }
163
+
164
+
165
+    /**
166
+     * copy file to owners trash
167
+     *
168
+     * @param string $sourcePath
169
+     * @param string $owner
170
+     * @param string $targetPath
171
+     * @param $user
172
+     * @param integer $timestamp
173
+     */
174
+    private static function copyFilesToUser($sourcePath, $owner, $targetPath, $user, $timestamp) {
175
+        self::setUpTrash($owner);
176
+
177
+        $targetFilename = basename($targetPath);
178
+        $targetLocation = dirname($targetPath);
179
+
180
+        $sourceFilename = basename($sourcePath);
181
+
182
+        $view = new View('/');
183
+
184
+        $target = $user . '/files_trashbin/files/' . $targetFilename . '.d' . $timestamp;
185
+        $source = $owner . '/files_trashbin/files/' . $sourceFilename . '.d' . $timestamp;
186
+        self::copy_recursive($source, $target, $view);
187
+
188
+
189
+        if ($view->file_exists($target)) {
190
+            $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
191
+            $result = $query->execute(array($targetFilename, $timestamp, $targetLocation, $user));
192
+            if (!$result) {
193
+                \OCP\Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated for the files owner', \OCP\Util::ERROR);
194
+            }
195
+        }
196
+    }
197
+
198
+
199
+    /**
200
+     * move file to the trash bin
201
+     *
202
+     * @param string $file_path path to the deleted file/directory relative to the files root directory
203
+     * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
204
+     *
205
+     * @return bool
206
+     */
207
+    public static function move2trash($file_path, $ownerOnly = false) {
208
+        // get the user for which the filesystem is setup
209
+        $root = Filesystem::getRoot();
210
+        list(, $user) = explode('/', $root);
211
+        list($owner, $ownerPath) = self::getUidAndFilename($file_path);
212
+
213
+        // if no owner found (ex: ext storage + share link), will use the current user's trashbin then
214
+        if (is_null($owner)) {
215
+            $owner = $user;
216
+            $ownerPath = $file_path;
217
+        }
218
+
219
+        $ownerView = new View('/' . $owner);
220
+        // file has been deleted in between
221
+        if (is_null($ownerPath) || $ownerPath === '' || !$ownerView->file_exists('/files/' . $ownerPath)) {
222
+            return true;
223
+        }
224
+
225
+        self::setUpTrash($user);
226
+        if ($owner !== $user) {
227
+            // also setup for owner
228
+            self::setUpTrash($owner);
229
+        }
230
+
231
+        $path_parts = pathinfo($ownerPath);
232
+
233
+        $filename = $path_parts['basename'];
234
+        $location = $path_parts['dirname'];
235
+        $timestamp = time();
236
+
237
+        // disable proxy to prevent recursive calls
238
+        $trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp;
239
+
240
+        /** @var \OC\Files\Storage\Storage $trashStorage */
241
+        list($trashStorage, $trashInternalPath) = $ownerView->resolvePath($trashPath);
242
+        /** @var \OC\Files\Storage\Storage $sourceStorage */
243
+        list($sourceStorage, $sourceInternalPath) = $ownerView->resolvePath('/files/' . $ownerPath);
244
+        try {
245
+            $moveSuccessful = true;
246
+            if ($trashStorage->file_exists($trashInternalPath)) {
247
+                $trashStorage->unlink($trashInternalPath);
248
+            }
249
+            $trashStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
250
+        } catch (\OCA\Files_Trashbin\Exceptions\CopyRecursiveException $e) {
251
+            $moveSuccessful = false;
252
+            if ($trashStorage->file_exists($trashInternalPath)) {
253
+                $trashStorage->unlink($trashInternalPath);
254
+            }
255
+            \OCP\Util::writeLog('files_trashbin', 'Couldn\'t move ' . $file_path . ' to the trash bin', \OCP\Util::ERROR);
256
+        }
257
+
258
+        if ($sourceStorage->file_exists($sourceInternalPath)) { // failed to delete the original file, abort
259
+            $sourceStorage->unlink($sourceInternalPath);
260
+            return false;
261
+        }
262
+
263
+        $trashStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
264
+
265
+        if ($moveSuccessful) {
266
+            $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
267
+            $result = $query->execute(array($filename, $timestamp, $location, $owner));
268
+            if (!$result) {
269
+                \OCP\Util::writeLog('files_trashbin', 'trash bin database couldn\'t be updated', \OCP\Util::ERROR);
270
+            }
271
+            \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', array('filePath' => Filesystem::normalizePath($file_path),
272
+                'trashPath' => Filesystem::normalizePath($filename . '.d' . $timestamp)));
273
+
274
+            self::retainVersions($filename, $owner, $ownerPath, $timestamp);
275
+
276
+            // if owner !== user we need to also add a copy to the users trash
277
+            if ($user !== $owner && $ownerOnly === false) {
278
+                self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
279
+            }
280
+        }
281
+
282
+        self::scheduleExpire($user);
283
+
284
+        // if owner !== user we also need to update the owners trash size
285
+        if ($owner !== $user) {
286
+            self::scheduleExpire($owner);
287
+        }
288
+
289
+        return $moveSuccessful;
290
+    }
291
+
292
+    /**
293
+     * Move file versions to trash so that they can be restored later
294
+     *
295
+     * @param string $filename of deleted file
296
+     * @param string $owner owner user id
297
+     * @param string $ownerPath path relative to the owner's home storage
298
+     * @param integer $timestamp when the file was deleted
299
+     */
300
+    private static function retainVersions($filename, $owner, $ownerPath, $timestamp) {
301
+        if (\OCP\App::isEnabled('files_versions') && !empty($ownerPath)) {
302
+
303
+            $user = User::getUser();
304
+            $rootView = new View('/');
305
+
306
+            if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) {
307
+                if ($owner !== $user) {
308
+                    self::copy_recursive($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp, $rootView);
309
+                }
310
+                self::move($rootView, $owner . '/files_versions/' . $ownerPath, $user . '/files_trashbin/versions/' . $filename . '.d' . $timestamp);
311
+            } else if ($versions = \OCA\Files_Versions\Storage::getVersions($owner, $ownerPath)) {
312
+
313
+                foreach ($versions as $v) {
314
+                    if ($owner !== $user) {
315
+                        self::copy($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $owner . '/files_trashbin/versions/' . $v['name'] . '.v' . $v['version'] . '.d' . $timestamp);
316
+                    }
317
+                    self::move($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $user . '/files_trashbin/versions/' . $filename . '.v' . $v['version'] . '.d' . $timestamp);
318
+                }
319
+            }
320
+        }
321
+    }
322
+
323
+    /**
324
+     * Move a file or folder on storage level
325
+     *
326
+     * @param View $view
327
+     * @param string $source
328
+     * @param string $target
329
+     * @return bool
330
+     */
331
+    private static function move(View $view, $source, $target) {
332
+        /** @var \OC\Files\Storage\Storage $sourceStorage */
333
+        list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
334
+        /** @var \OC\Files\Storage\Storage $targetStorage */
335
+        list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
336
+        /** @var \OC\Files\Storage\Storage $ownerTrashStorage */
337
+
338
+        $result = $targetStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
339
+        if ($result) {
340
+            $targetStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
341
+        }
342
+        return $result;
343
+    }
344
+
345
+    /**
346
+     * Copy a file or folder on storage level
347
+     *
348
+     * @param View $view
349
+     * @param string $source
350
+     * @param string $target
351
+     * @return bool
352
+     */
353
+    private static function copy(View $view, $source, $target) {
354
+        /** @var \OC\Files\Storage\Storage $sourceStorage */
355
+        list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
356
+        /** @var \OC\Files\Storage\Storage $targetStorage */
357
+        list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
358
+        /** @var \OC\Files\Storage\Storage $ownerTrashStorage */
359
+
360
+        $result = $targetStorage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
361
+        if ($result) {
362
+            $targetStorage->getUpdater()->update($targetInternalPath);
363
+        }
364
+        return $result;
365
+    }
366
+
367
+    /**
368
+     * Restore a file or folder from trash bin
369
+     *
370
+     * @param string $file path to the deleted file/folder relative to "files_trashbin/files/",
371
+     * including the timestamp suffix ".d12345678"
372
+     * @param string $filename name of the file/folder
373
+     * @param int $timestamp time when the file/folder was deleted
374
+     *
375
+     * @return bool true on success, false otherwise
376
+     */
377
+    public static function restore($file, $filename, $timestamp) {
378
+        $user = User::getUser();
379
+        $view = new View('/' . $user);
380
+
381
+        $location = '';
382
+        if ($timestamp) {
383
+            $location = self::getLocation($user, $filename, $timestamp);
384
+            if ($location === false) {
385
+                \OCP\Util::writeLog('files_trashbin', 'trash bin database inconsistent!', \OCP\Util::ERROR);
386
+            } else {
387
+                // if location no longer exists, restore file in the root directory
388
+                if ($location !== '/' &&
389
+                    (!$view->is_dir('files/' . $location) ||
390
+                        !$view->isCreatable('files/' . $location))
391
+                ) {
392
+                    $location = '';
393
+                }
394
+            }
395
+        }
396
+
397
+        // we need a  extension in case a file/dir with the same name already exists
398
+        $uniqueFilename = self::getUniqueFilename($location, $filename, $view);
399
+
400
+        $source = Filesystem::normalizePath('files_trashbin/files/' . $file);
401
+        $target = Filesystem::normalizePath('files/' . $location . '/' . $uniqueFilename);
402
+        if (!$view->file_exists($source)) {
403
+            return false;
404
+        }
405
+        $mtime = $view->filemtime($source);
406
+
407
+        // restore file
408
+        $restoreResult = $view->rename($source, $target);
409
+
410
+        // handle the restore result
411
+        if ($restoreResult) {
412
+            $fakeRoot = $view->getRoot();
413
+            $view->chroot('/' . $user . '/files');
414
+            $view->touch('/' . $location . '/' . $uniqueFilename, $mtime);
415
+            $view->chroot($fakeRoot);
416
+            \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', array('filePath' => Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename),
417
+                'trashPath' => Filesystem::normalizePath($file)));
418
+
419
+            self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp);
420
+
421
+            if ($timestamp) {
422
+                $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
423
+                $query->execute(array($user, $filename, $timestamp));
424
+            }
425
+
426
+            return true;
427
+        }
428
+
429
+        return false;
430
+    }
431
+
432
+    /**
433
+     * restore versions from trash bin
434
+     *
435
+     * @param View $view file view
436
+     * @param string $file complete path to file
437
+     * @param string $filename name of file once it was deleted
438
+     * @param string $uniqueFilename new file name to restore the file without overwriting existing files
439
+     * @param string $location location if file
440
+     * @param int $timestamp deletion time
441
+     * @return false|null
442
+     */
443
+    private static function restoreVersions(View $view, $file, $filename, $uniqueFilename, $location, $timestamp) {
444
+
445
+        if (\OCP\App::isEnabled('files_versions')) {
446
+
447
+            $user = User::getUser();
448
+            $rootView = new View('/');
449
+
450
+            $target = Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename);
451
+
452
+            list($owner, $ownerPath) = self::getUidAndFilename($target);
453
+
454
+            // file has been deleted in between
455
+            if (empty($ownerPath)) {
456
+                return false;
457
+            }
458
+
459
+            if ($timestamp) {
460
+                $versionedFile = $filename;
461
+            } else {
462
+                $versionedFile = $file;
463
+            }
464
+
465
+            if ($view->is_dir('/files_trashbin/versions/' . $file)) {
466
+                $rootView->rename(Filesystem::normalizePath($user . '/files_trashbin/versions/' . $file), Filesystem::normalizePath($owner . '/files_versions/' . $ownerPath));
467
+            } else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp, $user)) {
468
+                foreach ($versions as $v) {
469
+                    if ($timestamp) {
470
+                        $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
471
+                    } else {
472
+                        $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
473
+                    }
474
+                }
475
+            }
476
+        }
477
+    }
478
+
479
+    /**
480
+     * delete all files from the trash
481
+     */
482
+    public static function deleteAll() {
483
+        $user = User::getUser();
484
+        $view = new View('/' . $user);
485
+        $fileInfos = $view->getDirectoryContent('files_trashbin/files');
486
+
487
+        // Array to store the relative path in (after the file is deleted, the view won't be able to relativise the path anymore)
488
+        $filePaths = array();
489
+        foreach($fileInfos as $fileInfo){
490
+            $filePaths[] = $view->getRelativePath($fileInfo->getPath());
491
+        }
492
+        unset($fileInfos); // save memory
493
+
494
+        // Bulk PreDelete-Hook
495
+        \OC_Hook::emit('\OCP\Trashbin', 'preDeleteAll', array('paths' => $filePaths));
496
+
497
+        // Single-File Hooks
498
+        foreach($filePaths as $path){
499
+            self::emitTrashbinPreDelete($path);
500
+        }
501
+
502
+        // actual file deletion
503
+        $view->deleteAll('files_trashbin');
504
+        $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
505
+        $query->execute(array($user));
506
+
507
+        // Bulk PostDelete-Hook
508
+        \OC_Hook::emit('\OCP\Trashbin', 'deleteAll', array('paths' => $filePaths));
509
+
510
+        // Single-File Hooks
511
+        foreach($filePaths as $path){
512
+            self::emitTrashbinPostDelete($path);
513
+        }
514
+
515
+        $view->mkdir('files_trashbin');
516
+        $view->mkdir('files_trashbin/files');
517
+
518
+        return true;
519
+    }
520
+
521
+    /**
522
+     * wrapper function to emit the 'preDelete' hook of \OCP\Trashbin before a file is deleted
523
+     * @param string $path
524
+     */
525
+    protected static function emitTrashbinPreDelete($path){
526
+        \OC_Hook::emit('\OCP\Trashbin', 'preDelete', array('path' => $path));
527
+    }
528
+
529
+    /**
530
+     * wrapper function to emit the 'delete' hook of \OCP\Trashbin after a file has been deleted
531
+     * @param string $path
532
+     */
533
+    protected static function emitTrashbinPostDelete($path){
534
+        \OC_Hook::emit('\OCP\Trashbin', 'delete', array('path' => $path));
535
+    }
536
+
537
+    /**
538
+     * delete file from trash bin permanently
539
+     *
540
+     * @param string $filename path to the file
541
+     * @param string $user
542
+     * @param int $timestamp of deletion time
543
+     *
544
+     * @return int size of deleted files
545
+     */
546
+    public static function delete($filename, $user, $timestamp = null) {
547
+        $view = new View('/' . $user);
548
+        $size = 0;
549
+
550
+        if ($timestamp) {
551
+            $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
552
+            $query->execute(array($user, $filename, $timestamp));
553
+            $file = $filename . '.d' . $timestamp;
554
+        } else {
555
+            $file = $filename;
556
+        }
557
+
558
+        $size += self::deleteVersions($view, $file, $filename, $timestamp, $user);
559
+
560
+        if ($view->is_dir('/files_trashbin/files/' . $file)) {
561
+            $size += self::calculateSize(new View('/' . $user . '/files_trashbin/files/' . $file));
562
+        } else {
563
+            $size += $view->filesize('/files_trashbin/files/' . $file);
564
+        }
565
+        self::emitTrashbinPreDelete('/files_trashbin/files/' . $file);
566
+        $view->unlink('/files_trashbin/files/' . $file);
567
+        self::emitTrashbinPostDelete('/files_trashbin/files/' . $file);
568
+
569
+        return $size;
570
+    }
571
+
572
+    /**
573
+     * @param View $view
574
+     * @param string $file
575
+     * @param string $filename
576
+     * @param integer|null $timestamp
577
+     * @param string $user
578
+     * @return int
579
+     */
580
+    private static function deleteVersions(View $view, $file, $filename, $timestamp, $user) {
581
+        $size = 0;
582
+        if (\OCP\App::isEnabled('files_versions')) {
583
+            if ($view->is_dir('files_trashbin/versions/' . $file)) {
584
+                $size += self::calculateSize(new View('/' . $user . '/files_trashbin/versions/' . $file));
585
+                $view->unlink('files_trashbin/versions/' . $file);
586
+            } else if ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) {
587
+                foreach ($versions as $v) {
588
+                    if ($timestamp) {
589
+                        $size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
590
+                        $view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
591
+                    } else {
592
+                        $size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v);
593
+                        $view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v);
594
+                    }
595
+                }
596
+            }
597
+        }
598
+        return $size;
599
+    }
600
+
601
+    /**
602
+     * check to see whether a file exists in trashbin
603
+     *
604
+     * @param string $filename path to the file
605
+     * @param int $timestamp of deletion time
606
+     * @return bool true if file exists, otherwise false
607
+     */
608
+    public static function file_exists($filename, $timestamp = null) {
609
+        $user = User::getUser();
610
+        $view = new View('/' . $user);
611
+
612
+        if ($timestamp) {
613
+            $filename = $filename . '.d' . $timestamp;
614
+        } else {
615
+            $filename = $filename;
616
+        }
617
+
618
+        $target = Filesystem::normalizePath('files_trashbin/files/' . $filename);
619
+        return $view->file_exists($target);
620
+    }
621
+
622
+    /**
623
+     * deletes used space for trash bin in db if user was deleted
624
+     *
625
+     * @param string $uid id of deleted user
626
+     * @return bool result of db delete operation
627
+     */
628
+    public static function deleteUser($uid) {
629
+        $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
630
+        return $query->execute(array($uid));
631
+    }
632
+
633
+    /**
634
+     * calculate remaining free space for trash bin
635
+     *
636
+     * @param integer $trashbinSize current size of the trash bin
637
+     * @param string $user
638
+     * @return int available free space for trash bin
639
+     */
640
+    private static function calculateFreeSpace($trashbinSize, $user) {
641
+        $softQuota = true;
642
+        $userObject = \OC::$server->getUserManager()->get($user);
643
+        if(is_null($userObject)) {
644
+            return 0;
645
+        }
646
+        $quota = $userObject->getQuota();
647
+        if ($quota === null || $quota === 'none') {
648
+            $quota = Filesystem::free_space('/');
649
+            $softQuota = false;
650
+            // inf or unknown free space
651
+            if ($quota < 0) {
652
+                $quota = PHP_INT_MAX;
653
+            }
654
+        } else {
655
+            $quota = \OCP\Util::computerFileSize($quota);
656
+        }
657
+
658
+        // calculate available space for trash bin
659
+        // subtract size of files and current trash bin size from quota
660
+        if ($softQuota) {
661
+            $userFolder = \OC::$server->getUserFolder($user);
662
+            if(is_null($userFolder)) {
663
+                return 0;
664
+            }
665
+            $free = $quota - $userFolder->getSize(); // remaining free space for user
666
+            if ($free > 0) {
667
+                $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $trashbinSize; // how much space can be used for versions
668
+            } else {
669
+                $availableSpace = $free - $trashbinSize;
670
+            }
671
+        } else {
672
+            $availableSpace = $quota;
673
+        }
674
+
675
+        return $availableSpace;
676
+    }
677
+
678
+    /**
679
+     * resize trash bin if necessary after a new file was added to ownCloud
680
+     *
681
+     * @param string $user user id
682
+     */
683
+    public static function resizeTrash($user) {
684
+
685
+        $size = self::getTrashbinSize($user);
686
+
687
+        $freeSpace = self::calculateFreeSpace($size, $user);
688
+
689
+        if ($freeSpace < 0) {
690
+            self::scheduleExpire($user);
691
+        }
692
+    }
693
+
694
+    /**
695
+     * clean up the trash bin
696
+     *
697
+     * @param string $user
698
+     */
699
+    public static function expire($user) {
700
+        $trashBinSize = self::getTrashbinSize($user);
701
+        $availableSpace = self::calculateFreeSpace($trashBinSize, $user);
702
+
703
+        $dirContent = Helper::getTrashFiles('/', $user, 'mtime');
704
+
705
+        // delete all files older then $retention_obligation
706
+        list($delSize, $count) = self::deleteExpiredFiles($dirContent, $user);
707
+
708
+        $availableSpace += $delSize;
709
+
710
+        // delete files from trash until we meet the trash bin size limit again
711
+        self::deleteFiles(array_slice($dirContent, $count), $user, $availableSpace);
712
+    }
713
+
714
+    /**
715
+     * @param string $user
716
+     */
717
+    private static function scheduleExpire($user) {
718
+        // let the admin disable auto expire
719
+        $application = new Application();
720
+        $expiration = $application->getContainer()->query('Expiration');
721
+        if ($expiration->isEnabled()) {
722
+            \OC::$server->getCommandBus()->push(new Expire($user));
723
+        }
724
+    }
725
+
726
+    /**
727
+     * if the size limit for the trash bin is reached, we delete the oldest
728
+     * files in the trash bin until we meet the limit again
729
+     *
730
+     * @param array $files
731
+     * @param string $user
732
+     * @param int $availableSpace available disc space
733
+     * @return int size of deleted files
734
+     */
735
+    protected static function deleteFiles($files, $user, $availableSpace) {
736
+        $application = new Application();
737
+        $expiration = $application->getContainer()->query('Expiration');
738
+        $size = 0;
739
+
740
+        if ($availableSpace < 0) {
741
+            foreach ($files as $file) {
742
+                if ($availableSpace < 0 && $expiration->isExpired($file['mtime'], true)) {
743
+                    $tmp = self::delete($file['name'], $user, $file['mtime']);
744
+                    \OCP\Util::writeLog('files_trashbin', 'remove "' . $file['name'] . '" (' . $tmp . 'B) to meet the limit of trash bin size (50% of available quota)', \OCP\Util::INFO);
745
+                    $availableSpace += $tmp;
746
+                    $size += $tmp;
747
+                } else {
748
+                    break;
749
+                }
750
+            }
751
+        }
752
+        return $size;
753
+    }
754
+
755
+    /**
756
+     * delete files older then max storage time
757
+     *
758
+     * @param array $files list of files sorted by mtime
759
+     * @param string $user
760
+     * @return integer[] size of deleted files and number of deleted files
761
+     */
762
+    public static function deleteExpiredFiles($files, $user) {
763
+        $application = new Application();
764
+        $expiration = $application->getContainer()->query('Expiration');
765
+        $size = 0;
766
+        $count = 0;
767
+        foreach ($files as $file) {
768
+            $timestamp = $file['mtime'];
769
+            $filename = $file['name'];
770
+            if ($expiration->isExpired($timestamp)) {
771
+                $count++;
772
+                $size += self::delete($filename, $user, $timestamp);
773
+                \OC::$server->getLogger()->info(
774
+                    'Remove "' . $filename . '" from trashbin because it exceeds max retention obligation term.',
775
+                    ['app' => 'files_trashbin']
776
+                );
777
+            } else {
778
+                break;
779
+            }
780
+        }
781
+
782
+        return array($size, $count);
783
+    }
784
+
785
+    /**
786
+     * recursive copy to copy a whole directory
787
+     *
788
+     * @param string $source source path, relative to the users files directory
789
+     * @param string $destination destination path relative to the users root directoy
790
+     * @param View $view file view for the users root directory
791
+     * @return int
792
+     * @throws Exceptions\CopyRecursiveException
793
+     */
794
+    private static function copy_recursive($source, $destination, View $view) {
795
+        $size = 0;
796
+        if ($view->is_dir($source)) {
797
+            $view->mkdir($destination);
798
+            $view->touch($destination, $view->filemtime($source));
799
+            foreach ($view->getDirectoryContent($source) as $i) {
800
+                $pathDir = $source . '/' . $i['name'];
801
+                if ($view->is_dir($pathDir)) {
802
+                    $size += self::copy_recursive($pathDir, $destination . '/' . $i['name'], $view);
803
+                } else {
804
+                    $size += $view->filesize($pathDir);
805
+                    $result = $view->copy($pathDir, $destination . '/' . $i['name']);
806
+                    if (!$result) {
807
+                        throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
808
+                    }
809
+                    $view->touch($destination . '/' . $i['name'], $view->filemtime($pathDir));
810
+                }
811
+            }
812
+        } else {
813
+            $size += $view->filesize($source);
814
+            $result = $view->copy($source, $destination);
815
+            if (!$result) {
816
+                throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
817
+            }
818
+            $view->touch($destination, $view->filemtime($source));
819
+        }
820
+        return $size;
821
+    }
822
+
823
+    /**
824
+     * find all versions which belong to the file we want to restore
825
+     *
826
+     * @param string $filename name of the file which should be restored
827
+     * @param int $timestamp timestamp when the file was deleted
828
+     * @return array
829
+     */
830
+    private static function getVersionsFromTrash($filename, $timestamp, $user) {
831
+        $view = new View('/' . $user . '/files_trashbin/versions');
832
+        $versions = array();
833
+
834
+        //force rescan of versions, local storage may not have updated the cache
835
+        if (!self::$scannedVersions) {
836
+            /** @var \OC\Files\Storage\Storage $storage */
837
+            list($storage,) = $view->resolvePath('/');
838
+            $storage->getScanner()->scan('files_trashbin/versions');
839
+            self::$scannedVersions = true;
840
+        }
841
+
842
+        if ($timestamp) {
843
+            // fetch for old versions
844
+            $matches = $view->searchRaw($filename . '.v%.d' . $timestamp);
845
+            $offset = -strlen($timestamp) - 2;
846
+        } else {
847
+            $matches = $view->searchRaw($filename . '.v%');
848
+        }
849
+
850
+        if (is_array($matches)) {
851
+            foreach ($matches as $ma) {
852
+                if ($timestamp) {
853
+                    $parts = explode('.v', substr($ma['path'], 0, $offset));
854
+                    $versions[] = (end($parts));
855
+                } else {
856
+                    $parts = explode('.v', $ma);
857
+                    $versions[] = (end($parts));
858
+                }
859
+            }
860
+        }
861
+        return $versions;
862
+    }
863
+
864
+    /**
865
+     * find unique extension for restored file if a file with the same name already exists
866
+     *
867
+     * @param string $location where the file should be restored
868
+     * @param string $filename name of the file
869
+     * @param View $view filesystem view relative to users root directory
870
+     * @return string with unique extension
871
+     */
872
+    private static function getUniqueFilename($location, $filename, View $view) {
873
+        $ext = pathinfo($filename, PATHINFO_EXTENSION);
874
+        $name = pathinfo($filename, PATHINFO_FILENAME);
875
+        $l = \OC::$server->getL10N('files_trashbin');
876
+
877
+        $location = '/' . trim($location, '/');
878
+
879
+        // if extension is not empty we set a dot in front of it
880
+        if ($ext !== '') {
881
+            $ext = '.' . $ext;
882
+        }
883
+
884
+        if ($view->file_exists('files' . $location . '/' . $filename)) {
885
+            $i = 2;
886
+            $uniqueName = $name . " (" . $l->t("restored") . ")" . $ext;
887
+            while ($view->file_exists('files' . $location . '/' . $uniqueName)) {
888
+                $uniqueName = $name . " (" . $l->t("restored") . " " . $i . ")" . $ext;
889
+                $i++;
890
+            }
891
+
892
+            return $uniqueName;
893
+        }
894
+
895
+        return $filename;
896
+    }
897
+
898
+    /**
899
+     * get the size from a given root folder
900
+     *
901
+     * @param View $view file view on the root folder
902
+     * @return integer size of the folder
903
+     */
904
+    private static function calculateSize($view) {
905
+        $root = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . $view->getAbsolutePath('');
906
+        if (!file_exists($root)) {
907
+            return 0;
908
+        }
909
+        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($root), \RecursiveIteratorIterator::CHILD_FIRST);
910
+        $size = 0;
911
+
912
+        /**
913
+         * RecursiveDirectoryIterator on an NFS path isn't iterable with foreach
914
+         * This bug is fixed in PHP 5.5.9 or before
915
+         * See #8376
916
+         */
917
+        $iterator->rewind();
918
+        while ($iterator->valid()) {
919
+            $path = $iterator->current();
920
+            $relpath = substr($path, strlen($root) - 1);
921
+            if (!$view->is_dir($relpath)) {
922
+                $size += $view->filesize($relpath);
923
+            }
924
+            $iterator->next();
925
+        }
926
+        return $size;
927
+    }
928
+
929
+    /**
930
+     * get current size of trash bin from a given user
931
+     *
932
+     * @param string $user user who owns the trash bin
933
+     * @return integer trash bin size
934
+     */
935
+    private static function getTrashbinSize($user) {
936
+        $view = new View('/' . $user);
937
+        $fileInfo = $view->getFileInfo('/files_trashbin');
938
+        return isset($fileInfo['size']) ? $fileInfo['size'] : 0;
939
+    }
940
+
941
+    /**
942
+     * register hooks
943
+     */
944
+    public static function registerHooks() {
945
+        // create storage wrapper on setup
946
+        \OCP\Util::connectHook('OC_Filesystem', 'preSetup', 'OCA\Files_Trashbin\Storage', 'setupStorage');
947
+        //Listen to delete user signal
948
+        \OCP\Util::connectHook('OC_User', 'pre_deleteUser', 'OCA\Files_Trashbin\Hooks', 'deleteUser_hook');
949
+        //Listen to post write hook
950
+        \OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\Files_Trashbin\Hooks', 'post_write_hook');
951
+        // pre and post-rename, disable trash logic for the copy+unlink case
952
+        \OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook');
953
+        \OCP\Util::connectHook('OC_Filesystem', 'rename', 'OCA\Files_Trashbin\Storage', 'preRenameHook');
954
+        \OCP\Util::connectHook('OC_Filesystem', 'post_rename', 'OCA\Files_Trashbin\Storage', 'postRenameHook');
955
+    }
956
+
957
+    /**
958
+     * check if trash bin is empty for a given user
959
+     *
960
+     * @param string $user
961
+     * @return bool
962
+     */
963
+    public static function isEmpty($user) {
964
+
965
+        $view = new View('/' . $user . '/files_trashbin');
966
+        if ($view->is_dir('/files') && $dh = $view->opendir('/files')) {
967
+            while ($file = readdir($dh)) {
968
+                if (!Filesystem::isIgnoredDir($file)) {
969
+                    return false;
970
+                }
971
+            }
972
+        }
973
+        return true;
974
+    }
975
+
976
+    /**
977
+     * @param $path
978
+     * @return string
979
+     */
980
+    public static function preview_icon($path) {
981
+        return \OCP\Util::linkToRoute('core_ajax_trashbin_preview', array('x' => 32, 'y' => 32, 'file' => $path));
982
+    }
983 983
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Controller/PreviewController.php 1 patch
Indentation   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -35,85 +35,85 @@
 block discarded – undo
35 35
 
36 36
 class PreviewController extends Controller {
37 37
 
38
-	/** @var IRootFolder */
39
-	private $rootFolder;
38
+    /** @var IRootFolder */
39
+    private $rootFolder;
40 40
 
41
-	/** @var string */
42
-	private $userId;
41
+    /** @var string */
42
+    private $userId;
43 43
 
44
-	/** @var IMimeTypeDetector */
45
-	private $mimeTypeDetector;
44
+    /** @var IMimeTypeDetector */
45
+    private $mimeTypeDetector;
46 46
 
47
-	/** @var IPreview */
48
-	private $previewManager;
47
+    /** @var IPreview */
48
+    private $previewManager;
49 49
 
50
-	/**
51
-	 * @param string $appName
52
-	 * @param IRequest $request
53
-	 * @param IRootFolder $rootFolder
54
-	 * @param $userId
55
-	 * @param IMimeTypeDetector $mimeTypeDetector
56
-	 * @param IPreview $previewManager
57
-	 */
58
-	public function __construct($appName,
59
-								IRequest $request,
60
-								IRootFolder $rootFolder,
61
-								$userId,
62
-								IMimeTypeDetector $mimeTypeDetector,
63
-								IPreview $previewManager) {
64
-		parent::__construct($appName, $request);
50
+    /**
51
+     * @param string $appName
52
+     * @param IRequest $request
53
+     * @param IRootFolder $rootFolder
54
+     * @param $userId
55
+     * @param IMimeTypeDetector $mimeTypeDetector
56
+     * @param IPreview $previewManager
57
+     */
58
+    public function __construct($appName,
59
+                                IRequest $request,
60
+                                IRootFolder $rootFolder,
61
+                                $userId,
62
+                                IMimeTypeDetector $mimeTypeDetector,
63
+                                IPreview $previewManager) {
64
+        parent::__construct($appName, $request);
65 65
 
66
-		$this->rootFolder = $rootFolder;
67
-		$this->userId = $userId;
68
-		$this->mimeTypeDetector = $mimeTypeDetector;
69
-		$this->previewManager = $previewManager;
70
-	}
66
+        $this->rootFolder = $rootFolder;
67
+        $this->userId = $userId;
68
+        $this->mimeTypeDetector = $mimeTypeDetector;
69
+        $this->previewManager = $previewManager;
70
+    }
71 71
 
72
-	/**
73
-	 * @NoAdminRequired
74
-	 * @NoCSRFRequired
75
-	 *
76
-	 * @param string $file
77
-	 * @param int $x
78
-	 * @param int $y
79
-	 * @return DataResponse|Http\FileDisplayResponse
80
-	 */
81
-	public function getPreview(
82
-		$file = '',
83
-		$x = 44,
84
-		$y = 44
85
-	) {
86
-		if ($file === '') {
87
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
88
-		}
72
+    /**
73
+     * @NoAdminRequired
74
+     * @NoCSRFRequired
75
+     *
76
+     * @param string $file
77
+     * @param int $x
78
+     * @param int $y
79
+     * @return DataResponse|Http\FileDisplayResponse
80
+     */
81
+    public function getPreview(
82
+        $file = '',
83
+        $x = 44,
84
+        $y = 44
85
+    ) {
86
+        if ($file === '') {
87
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
88
+        }
89 89
 
90
-		if ($x === 0 || $y === 0) {
91
-			return new DataResponse([], Http::STATUS_BAD_REQUEST);
92
-		}
90
+        if ($x === 0 || $y === 0) {
91
+            return new DataResponse([], Http::STATUS_BAD_REQUEST);
92
+        }
93 93
 
94
-		try {
95
-			$userFolder = $this->rootFolder->getUserFolder($this->userId);
96
-			/** @var Folder $trash */
97
-			$trash = $userFolder->getParent()->get('files_trashbin/files');
98
-			$trashFile = $trash->get($file);
94
+        try {
95
+            $userFolder = $this->rootFolder->getUserFolder($this->userId);
96
+            /** @var Folder $trash */
97
+            $trash = $userFolder->getParent()->get('files_trashbin/files');
98
+            $trashFile = $trash->get($file);
99 99
 
100
-			if ($trashFile instanceof Folder) {
101
-				return new DataResponse([], Http::STATUS_BAD_REQUEST);
102
-			}
100
+            if ($trashFile instanceof Folder) {
101
+                return new DataResponse([], Http::STATUS_BAD_REQUEST);
102
+            }
103 103
 
104
-			/** @var File $trashFile */
105
-			$fileName = $trashFile->getName();
106
-			$i = strrpos($fileName, '.');
107
-			if ($i !== false) {
108
-				$fileName = substr($fileName, 0, $i);
109
-			}
104
+            /** @var File $trashFile */
105
+            $fileName = $trashFile->getName();
106
+            $i = strrpos($fileName, '.');
107
+            if ($i !== false) {
108
+                $fileName = substr($fileName, 0, $i);
109
+            }
110 110
 
111
-			$mimeType = $this->mimeTypeDetector->detectPath($fileName);
111
+            $mimeType = $this->mimeTypeDetector->detectPath($fileName);
112 112
 
113
-			$f = $this->previewManager->getPreview($trashFile, $x, $y, true, IPreview::MODE_FILL, $mimeType);
114
-			return new Http\FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
115
-		} catch (NotFoundException $e) {
116
-			return new DataResponse([], Http::STATUS_NOT_FOUND);
117
-		}
118
-	}
113
+            $f = $this->previewManager->getPreview($trashFile, $x, $y, true, IPreview::MODE_FILL, $mimeType);
114
+            return new Http\FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
115
+        } catch (NotFoundException $e) {
116
+            return new DataResponse([], Http::STATUS_NOT_FOUND);
117
+        }
118
+    }
119 119
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/AppInfo/Application.php 1 patch
Indentation   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -27,23 +27,23 @@
 block discarded – undo
27 27
 use OCA\Files_Trashbin\Expiration;
28 28
 
29 29
 class Application extends App {
30
-	public function __construct (array $urlParams = []) {
31
-		parent::__construct('files_trashbin', $urlParams);
30
+    public function __construct (array $urlParams = []) {
31
+        parent::__construct('files_trashbin', $urlParams);
32 32
 
33
-		$container = $this->getContainer();
34
-		/*
33
+        $container = $this->getContainer();
34
+        /*
35 35
 		 * Register capabilities
36 36
 		 */
37
-		$container->registerCapability('OCA\Files_Trashbin\Capabilities');
37
+        $container->registerCapability('OCA\Files_Trashbin\Capabilities');
38 38
 
39
-		/*
39
+        /*
40 40
 		 * Register expiration
41 41
 		 */
42
-		$container->registerService('Expiration', function($c) {
43
-			return  new Expiration(
44
-				$c->query('ServerContainer')->getConfig(),
45
-				$c->query('OCP\AppFramework\Utility\ITimeFactory')
46
-			);
47
-		});
48
-	}
42
+        $container->registerService('Expiration', function($c) {
43
+            return  new Expiration(
44
+                $c->query('ServerContainer')->getConfig(),
45
+                $c->query('OCP\AppFramework\Utility\ITimeFactory')
46
+            );
47
+        });
48
+    }
49 49
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Helper.php 1 patch
Indentation   +81 added lines, -81 removed lines patch added patch discarded remove patch
@@ -30,92 +30,92 @@
 block discarded – undo
30 30
 use OCP\Files\Cache\ICacheEntry;
31 31
 
32 32
 class Helper {
33
-	/**
34
-	 * Retrieves the contents of a trash bin directory.
35
-	 *
36
-	 * @param string $dir path to the directory inside the trashbin
37
-	 * or empty to retrieve the root of the trashbin
38
-	 * @param string $user
39
-	 * @param string $sortAttribute attribute to sort on or empty to disable sorting
40
-	 * @param bool $sortDescending true for descending sort, false otherwise
41
-	 * @return \OCP\Files\FileInfo[]
42
-	 */
43
-	public static function getTrashFiles($dir, $user, $sortAttribute = '', $sortDescending = false) {
44
-		$result = array();
45
-		$timestamp = null;
33
+    /**
34
+     * Retrieves the contents of a trash bin directory.
35
+     *
36
+     * @param string $dir path to the directory inside the trashbin
37
+     * or empty to retrieve the root of the trashbin
38
+     * @param string $user
39
+     * @param string $sortAttribute attribute to sort on or empty to disable sorting
40
+     * @param bool $sortDescending true for descending sort, false otherwise
41
+     * @return \OCP\Files\FileInfo[]
42
+     */
43
+    public static function getTrashFiles($dir, $user, $sortAttribute = '', $sortDescending = false) {
44
+        $result = array();
45
+        $timestamp = null;
46 46
 
47
-		$view = new \OC\Files\View('/' . $user . '/files_trashbin/files');
47
+        $view = new \OC\Files\View('/' . $user . '/files_trashbin/files');
48 48
 
49
-		if (ltrim($dir, '/') !== '' && !$view->is_dir($dir)) {
50
-			throw new \Exception('Directory does not exists');
51
-		}
49
+        if (ltrim($dir, '/') !== '' && !$view->is_dir($dir)) {
50
+            throw new \Exception('Directory does not exists');
51
+        }
52 52
 
53
-		$mount = $view->getMount($dir);
54
-		$storage = $mount->getStorage();
55
-		$absoluteDir = $view->getAbsolutePath($dir);
56
-		$internalPath = $mount->getInternalPath($absoluteDir);
53
+        $mount = $view->getMount($dir);
54
+        $storage = $mount->getStorage();
55
+        $absoluteDir = $view->getAbsolutePath($dir);
56
+        $internalPath = $mount->getInternalPath($absoluteDir);
57 57
 
58
-		$originalLocations = \OCA\Files_Trashbin\Trashbin::getLocations($user);
59
-		$dirContent = $storage->getCache()->getFolderContents($mount->getInternalPath($view->getAbsolutePath($dir)));
60
-		foreach ($dirContent as $entry) {
61
-			$entryName = $entry->getName();
62
-			$id = $entry->getId();
63
-			$name = $entryName;
64
-			if ($dir === '' || $dir === '/') {
65
-				$pathparts = pathinfo($entryName);
66
-				$timestamp = substr($pathparts['extension'], 1);
67
-				$name = $pathparts['filename'];
58
+        $originalLocations = \OCA\Files_Trashbin\Trashbin::getLocations($user);
59
+        $dirContent = $storage->getCache()->getFolderContents($mount->getInternalPath($view->getAbsolutePath($dir)));
60
+        foreach ($dirContent as $entry) {
61
+            $entryName = $entry->getName();
62
+            $id = $entry->getId();
63
+            $name = $entryName;
64
+            if ($dir === '' || $dir === '/') {
65
+                $pathparts = pathinfo($entryName);
66
+                $timestamp = substr($pathparts['extension'], 1);
67
+                $name = $pathparts['filename'];
68 68
 
69
-			} else if ($timestamp === null) {
70
-				// for subfolders we need to calculate the timestamp only once
71
-				$parts = explode('/', ltrim($dir, '/'));
72
-				$timestamp = substr(pathinfo($parts[0], PATHINFO_EXTENSION), 1);
73
-			}
74
-			$originalPath = '';
75
-			if (isset($originalLocations[$id][$timestamp])) {
76
-				$originalPath = $originalLocations[$id][$timestamp];
77
-				if (substr($originalPath, -1) === '/') {
78
-					$originalPath = substr($originalPath, 0, -1);
79
-				}
80
-			}
81
-			$type = $entry->getMimeType() === ICacheEntry::DIRECTORY_MIMETYPE ? 'dir' : 'file';
82
-			$i = array(
83
-				'name' => $name,
84
-				'mtime' => $timestamp,
85
-				'mimetype' => $type === 'dir' ? 'httpd/unix-directory' : \OC::$server->getMimeTypeDetector()->detectPath($name),
86
-				'type' => $type,
87
-				'directory' => ($dir === '/') ? '' : $dir,
88
-				'size' => $entry->getSize(),
89
-				'etag' => '',
90
-				'permissions' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE
91
-			);
92
-			if ($originalPath) {
93
-				$i['extraData'] = $originalPath . '/' . $id;
94
-			}
95
-			$result[] = new FileInfo($absoluteDir . '/' . $i['name'], $storage, $internalPath . '/' . $i['name'], $i, $mount);
96
-		}
69
+            } else if ($timestamp === null) {
70
+                // for subfolders we need to calculate the timestamp only once
71
+                $parts = explode('/', ltrim($dir, '/'));
72
+                $timestamp = substr(pathinfo($parts[0], PATHINFO_EXTENSION), 1);
73
+            }
74
+            $originalPath = '';
75
+            if (isset($originalLocations[$id][$timestamp])) {
76
+                $originalPath = $originalLocations[$id][$timestamp];
77
+                if (substr($originalPath, -1) === '/') {
78
+                    $originalPath = substr($originalPath, 0, -1);
79
+                }
80
+            }
81
+            $type = $entry->getMimeType() === ICacheEntry::DIRECTORY_MIMETYPE ? 'dir' : 'file';
82
+            $i = array(
83
+                'name' => $name,
84
+                'mtime' => $timestamp,
85
+                'mimetype' => $type === 'dir' ? 'httpd/unix-directory' : \OC::$server->getMimeTypeDetector()->detectPath($name),
86
+                'type' => $type,
87
+                'directory' => ($dir === '/') ? '' : $dir,
88
+                'size' => $entry->getSize(),
89
+                'etag' => '',
90
+                'permissions' => Constants::PERMISSION_ALL - Constants::PERMISSION_SHARE
91
+            );
92
+            if ($originalPath) {
93
+                $i['extraData'] = $originalPath . '/' . $id;
94
+            }
95
+            $result[] = new FileInfo($absoluteDir . '/' . $i['name'], $storage, $internalPath . '/' . $i['name'], $i, $mount);
96
+        }
97 97
 
98
-		if ($sortAttribute !== '') {
99
-			return \OCA\Files\Helper::sortFiles($result, $sortAttribute, $sortDescending);
100
-		}
101
-		return $result;
102
-	}
98
+        if ($sortAttribute !== '') {
99
+            return \OCA\Files\Helper::sortFiles($result, $sortAttribute, $sortDescending);
100
+        }
101
+        return $result;
102
+    }
103 103
 
104
-	/**
105
-	 * Format file infos for JSON
106
-	 *
107
-	 * @param \OCP\Files\FileInfo[] $fileInfos file infos
108
-	 */
109
-	public static function formatFileInfos($fileInfos) {
110
-		$files = array();
111
-		$id = 0;
112
-		foreach ($fileInfos as $i) {
113
-			$entry = \OCA\Files\Helper::formatFileInfo($i);
114
-			$entry['id'] = $id++;
115
-			$entry['etag'] = $entry['mtime']; // add fake etag, it is only needed to identify the preview image
116
-			$entry['permissions'] = \OCP\Constants::PERMISSION_READ;
117
-			$files[] = $entry;
118
-		}
119
-		return $files;
120
-	}
104
+    /**
105
+     * Format file infos for JSON
106
+     *
107
+     * @param \OCP\Files\FileInfo[] $fileInfos file infos
108
+     */
109
+    public static function formatFileInfos($fileInfos) {
110
+        $files = array();
111
+        $id = 0;
112
+        foreach ($fileInfos as $i) {
113
+            $entry = \OCA\Files\Helper::formatFileInfo($i);
114
+            $entry['id'] = $id++;
115
+            $entry['etag'] = $entry['mtime']; // add fake etag, it is only needed to identify the preview image
116
+            $entry['permissions'] = \OCP\Constants::PERMISSION_READ;
117
+            $files[] = $entry;
118
+        }
119
+        return $files;
120
+    }
121 121
 }
Please login to merge, or discard this patch.