Issues (195)

lib/Controller/FileOperationController.php (16 issues)

1
<?php
2
3
/**
4
 * @copyright Copyright (c) 2018 Matthias Held <[email protected]>
5
 * @author Matthias Held <[email protected]>
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
namespace OCA\RansomwareDetection\Controller;
23
24
use OCA\RansomwareDetection\Monitor;
25
use OCA\RansomwareDetection\Classifier;
26
use OCA\RansomwareDetection\AppInfo\Application;
27
use OCA\RansomwareDetection\Db\FileOperation;
28
use OCA\RansomwareDetection\Service\FileOperationService;
29
use OCA\Files_Trashbin\Trashbin;
0 ignored issues
show
The type OCA\Files_Trashbin\Trashbin was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
30
use OCA\Files_Trashbin\Helper;
0 ignored issues
show
The type OCA\Files_Trashbin\Helper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
use OCP\AppFramework\Http;
0 ignored issues
show
The type OCP\AppFramework\Http was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use OCP\AppFramework\Http\JSONResponse;
0 ignored issues
show
The type OCP\AppFramework\Http\JSONResponse was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
33
use OCP\AppFramework\Controller;
0 ignored issues
show
The type OCP\AppFramework\Controller was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
use OCP\Files\File;
0 ignored issues
show
The type OCP\Files\File was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
35
use OCP\Files\Folder;
0 ignored issues
show
The type OCP\Files\Folder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
36
use OCP\IConfig;
0 ignored issues
show
The type OCP\IConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
37
use OCP\IUserSession;
0 ignored issues
show
The type OCP\IUserSession was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
38
use OCP\IRequest;
0 ignored issues
show
The type OCP\IRequest was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
39
use OCP\ILogger;
0 ignored issues
show
The type OCP\ILogger was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
40
41
class FileOperationController extends Controller
42
{
43
    /** @var IConfig */
44
    protected $config;
45
46
    /** @var IUserSession */
47
    protected $userSession;
48
49
    /** @var ILogger */
50
    protected $logger;
51
52
    /** @var Folder */
53
    protected $userFolder;
54
55
    /** @var FileOperationService */
56
    protected $service;
57
58
    /** @var Classifier */
59
    protected $classifier;
60
61
    /** @var string */
62
    protected $userId;
63
64
    /**
65
     * @param string               $appName
66
     * @param IRequest             $request
67
     * @param IUserSession         $userSession
68
     * @param IConfig              $config
69
     * @param ILogger              $logger
70
     * @param Folder               $userFolder
71
     * @param FileOperationService $service
72
     * @param Classifier           $classifier
73
     * @param string               $userId
74
     */
75
    public function __construct(
76
        $appName,
77
        IRequest $request,
78
        IUserSession $userSession,
79
        IConfig $config,
80
        ILogger $logger,
81
        Folder $userFolder,
82
        FileOperationService $service,
83
        Classifier $classifier,
84
        $userId
85
    ) {
86
        parent::__construct($appName, $request);
87
88
        $this->config = $config;
89
        $this->userSession = $userSession;
90
        $this->userFolder = $userFolder;
91
        $this->logger = $logger;
92
        $this->service = $service;
93
        $this->classifier = $classifier;
94
        $this->userId = $userId;
95
    }
96
97
    /**
98
     * Lists the files.
99
     *
100
     * @NoAdminRequired
101
     * @NoCSRFRequired
102
     *
103
     * @return JSONResponse
104
     */
105
    public function findAll()
106
    {
107
        $files = $this->service->findAll();
108
109
        foreach ($files as $file) {
110
            $this->classifier->classifyFile($file);
111
        }
112
113
        return new JSONResponse($files, Http::STATUS_OK);
114
    }
115
116
    /**
117
     * Find file with id.
118
     *
119
     * @NoAdminRequired
120
     * @NoCSRFRequired
121
     *
122
     * @return JSONResponse
123
     */
124
    public function find($id)
125
    {
126
        $file = $this->service->find($id);
127
128
        $this->classifier->classifyFile($file);
129
130
        return new JSONResponse($file, Http::STATUS_OK);
131
    }
132
133
    /**
134
     * Recover files from trashbin or remove them from normal storage.
135
     *
136
     * @NoAdminRequired
137
     * @NoCSRFRequired
138
     *
139
     * @param array $ids file operation id
140
     *
141
     * @return JSONResponse
142
     */
143
    public function recover($ids)
144
    {
145
        $deleted = 0;
146
        $recovered = 0;
147
        $filesRecovered = array();
148
        $error = false;
149
        $badRequest = false;
150
151
        foreach ($ids as $id) {
152
            try {
153
                $file = $this->service->find($id);
154
                switch ($file->getCommand()) {
155
                    case Monitor::WRITE:
156
                        // Recover new created files by deleting them
157
                        $filePath = $file->getPath().'/'.$file->getOriginalName();
158
                        if ($this->deleteFromStorage($filePath)) {
159
                            $this->service->deleteById($id, true);
160
161
                            $deleted++;
162
                            array_push($filesRecovered, $id);
163
                        } else {
164
                            // File cannot be deleted
165
                            $error = true;
166
                        }
167
                        break;
168
                    case Monitor::DELETE:
169
                        // Recover deleted files by restoring them from the trashbin
170
                        // It's not necessary to use the real path
171
                        $dir = '/';
172
                        $candidate = $this->findCandidateToRestore($dir, $file->getOriginalName());
173
                        if ($candidate !== null) {
174
                            $path = $dir.'/'.$candidate['name'].'.d'.$candidate['mtime'];
175
                            if (Trashbin::restore($path, $candidate['name'], $candidate['mtime']) !== false) {
176
                                $this->service->deleteById($id, true);
177
178
                                $recovered++;
179
                                array_push($filesRecovered, $id);
180
                            }
181
                            // File does not exist
182
                            $badRequest = false;
183
                        } else {
184
                            // No candidate found
185
                            $badRequest = false;
186
                        }
187
                        break;
188
                    case Monitor::RENAME:
189
                        $this->service->deleteById($id, true);
190
191
                        $deleted++;
192
                        array_push($filesRecovered, $id);
193
                        break;
194
                    case Monitor::CREATE:
195
                        // Recover new created files/folders
196
                        $filePath = $file->getPath().'/'.$file->getOriginalName();
197
                        if ($this->deleteFromStorage($filePath)) {
198
                            $this->service->deleteById($id, true);
199
200
                            $deleted++;
201
                            array_push($filesRecovered, $id);
202
                        } else {
203
                            // File cannot be deleted
204
                            $error = true;
205
                        }
206
                        break;
207
                    default:
208
                        // All other commands need no recovery
209
                        $this->service->deleteById($id, false);
210
211
                        $deleted++;
212
                        array_push($filesRecovered, $id);
213
                        break;
214
                    }
215
            } catch (\OCP\AppFramework\Db\MultipleObjectsReturnedException $exception) {
0 ignored issues
show
The type OCP\AppFramework\Db\Mult...bjectsReturnedException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
216
                // Found more than one with the same file name
217
                $this->logger->debug('recover: Found more than one with the same file name.', array('app' => Application::APP_ID));
218
219
                $badRequest = false;
220
            } catch (\OCP\AppFramework\Db\DoesNotExistException $exception) {
0 ignored issues
show
The type OCP\AppFramework\Db\DoesNotExistException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
221
                // Nothing found
222
                $this->logger->debug('recover: Files does not exist.', array('app' => Application::APP_ID));
223
224
                $badRequest = false;
225
            }
226
        }
227
        if ($error) {
228
            return new JSONResponse(array('recovered' => $recovered, 'deleted' => $deleted, 'filesRecovered' => $filesRecovered), Http::STATUS_INTERNAL_SERVER_ERROR);
229
        }
230
        if ($badRequest) {
0 ignored issues
show
The condition $badRequest is always false.
Loading history...
231
            return new JSONResponse(array('recovered' => $recovered, 'deleted' => $deleted, 'filesRecovered' => $filesRecovered), Http::STATUS_BAD_REQUEST);
232
        }
233
        return new JSONResponse(array('recovered' => $recovered, 'deleted' => $deleted, 'filesRecovered' => $filesRecovered), Http::STATUS_OK);
234
    }
235
236
    /**
237
     * Deletes a file from the storage.
238
     *
239
     * @param string $path
240
     *
241
     * @return bool
242
     */
243
    private function deleteFromStorage($path)
244
    {
245
        try {
246
            $node = $this->userFolder->get($path);
247
            if ($node->isDeletable()) {
248
                $node->delete();
249
            } else {
250
                return false;
251
            }
252
253
            return true;
254
        } catch (\OCP\Files\NotFoundException $exception) {
0 ignored issues
show
The type OCP\Files\NotFoundException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
255
            // Nothing found
256
            $this->logger->debug('deleteFromStorage: Not found exception.', array('app' => Application::APP_ID));
257
258
            return true;
259
        }
260
    }
261
262
    /**
263
     * Finds a candidate to restore if a file with the specific does not exist.
264
     *
265
     * @param string $dir
266
     * @param string $fileName
267
     *
268
     * @return FileInfo
0 ignored issues
show
The type OCA\RansomwareDetection\Controller\FileInfo was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
269
     */
270
    private function findCandidateToRestore($dir, $fileName)
271
    {
272
        $files = array();
273
        $trashBinFiles = $this->getTrashFiles($dir);
274
275
        foreach ($trashBinFiles as $trashBinFile) {
276
            if (strcmp($trashBinFile['name'], $fileName) === 0) {
277
                $files[] = $trashBinFile;
278
            }
279
        }
280
281
        return array_pop($files);
282
    }
283
284
    /**
285
     * Workaround for testing.
286
     *
287
     * @param string $dir
288
     *
289
     * @return array
290
     */
291
    private function getTrashFiles($dir)
292
    {
293
        return Helper::getTrashFiles($dir, $this->userId, 'mtime', false);
294
    }
295
296
}