Completed
Push — master ( 3da92a...bdf411 )
by Robin
15:41
created

SMB::checkDependencies()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 4
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Jesús Macias <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Juan Pablo Villafañez <[email protected]>
9
 * @author Juan Pablo Villafáñez <[email protected]>
10
 * @author Jörn Friedrich Dreyer <[email protected]>
11
 * @author Michael Gapczynski <[email protected]>
12
 * @author Morris Jobke <[email protected]>
13
 * @author Philipp Kapfer <[email protected]>
14
 * @author Robin Appelman <[email protected]>
15
 * @author Robin McCorkell <[email protected]>
16
 * @author Thomas Müller <[email protected]>
17
 * @author Vincent Petry <[email protected]>
18
 *
19
 * @license AGPL-3.0
20
 *
21
 * This code is free software: you can redistribute it and/or modify
22
 * it under the terms of the GNU Affero General Public License, version 3,
23
 * as published by the Free Software Foundation.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
 * GNU Affero General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Affero General Public License, version 3,
31
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
32
 *
33
 */
34
35
namespace OCA\Files_External\Lib\Storage;
36
37
use Icewind\SMB\Exception\AlreadyExistsException;
38
use Icewind\SMB\Exception\ConnectException;
39
use Icewind\SMB\Exception\Exception;
40
use Icewind\SMB\Exception\ForbiddenException;
41
use Icewind\SMB\Exception\NotFoundException;
42
use Icewind\SMB\IFileInfo;
43
use Icewind\SMB\NativeServer;
44
use Icewind\SMB\Server;
45
use Icewind\Streams\CallbackWrapper;
46
use Icewind\Streams\IteratorDirectory;
47
use OC\Cache\CappedMemoryCache;
48
use OC\Files\Filesystem;
49
use OC\Files\Storage\Common;
50
use OCA\Files_External\Lib\Notify\SMBNotifyHandler;
51
use OCP\Files\Notify\IChange;
52
use OCP\Files\Notify\IRenameChange;
53
use OCP\Files\Storage\INotifyStorage;
54
use OCP\Files\StorageNotAvailableException;
55
use OCP\Util;
56
57
class SMB extends Common implements INotifyStorage {
58
	/**
59
	 * @var \Icewind\SMB\Server
60
	 */
61
	protected $server;
62
63
	/**
64
	 * @var \Icewind\SMB\Share
65
	 */
66
	protected $share;
67
68
	/**
69
	 * @var string
70
	 */
71
	protected $root;
72
73
	/**
74
	 * @var \Icewind\SMB\FileInfo[]
75
	 */
76
	protected $statCache;
77
78
	public function __construct($params) {
79
		if (isset($params['host']) && isset($params['user']) && isset($params['password']) && isset($params['share'])) {
80
			if (Server::NativeAvailable()) {
81
				$this->server = new NativeServer($params['host'], $params['user'], $params['password']);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Icewind\SMB\NativeS...], $params['password']) of type object<Icewind\SMB\NativeServer> is incompatible with the declared type object<Icewind\SMB\Server> of property $server.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
82
			} else {
83
				$this->server = new Server($params['host'], $params['user'], $params['password']);
84
			}
85
			$this->share = $this->server->getShare(trim($params['share'], '/'));
86
87
			$this->root = isset($params['root']) ? $params['root'] : '/';
88 View Code Duplication
			if (!$this->root || $this->root[0] !== '/') {
89
				$this->root = '/' . $this->root;
90
			}
91
			if (substr($this->root, -1, 1) !== '/') {
92
				$this->root .= '/';
93
			}
94
		} else {
95
			throw new \Exception('Invalid configuration');
96
		}
97
		$this->statCache = new CappedMemoryCache();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \OC\Cache\CappedMemoryCache() of type object<OC\Cache\CappedMemoryCache> is incompatible with the declared type array<integer,object<Icewind\SMB\FileInfo>> of property $statCache.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
98
		parent::__construct($params);
99
	}
100
101
	/**
102
	 * @return string
103
	 */
104
	public function getId() {
105
		// FIXME: double slash to keep compatible with the old storage ids,
106
		// failure to do so will lead to creation of a new storage id and
107
		// loss of shares from the storage
108
		return 'smb::' . $this->server->getUser() . '@' . $this->server->getHost() . '//' . $this->share->getName() . '/' . $this->root;
109
	}
110
111
	/**
112
	 * @param string $path
113
	 * @return string
114
	 */
115
	protected function buildPath($path) {
116
		return Filesystem::normalizePath($this->root . '/' . $path, true, false, true);
117
	}
118
119 View Code Duplication
	protected function relativePath($fullPath) {
120
		if ($fullPath === $this->root) {
121
			return '';
122
		} else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
123
			return substr($fullPath, strlen($this->root));
124
		} else {
125
			return null;
126
		}
127
	}
128
129
	/**
130
	 * @param string $path
131
	 * @return \Icewind\SMB\IFileInfo
132
	 * @throws StorageNotAvailableException
133
	 */
134
	protected function getFileInfo($path) {
135
		try {
136
			$path = $this->buildPath($path);
137
			if (!isset($this->statCache[$path])) {
138
				$this->statCache[$path] = $this->share->stat($path);
139
			}
140
			return $this->statCache[$path];
141
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
142
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
143
		}
144
	}
145
146
	/**
147
	 * @param string $path
148
	 * @return \Icewind\SMB\IFileInfo[]
149
	 * @throws StorageNotAvailableException
150
	 */
151
	protected function getFolderContents($path) {
152
		try {
153
			$path = $this->buildPath($path);
154
			$files = $this->share->dir($path);
155
			foreach ($files as $file) {
156
				$this->statCache[$path . '/' . $file->getName()] = $file;
157
			}
158
			return array_filter($files, function (IFileInfo $file) {
159
				return !$file->isHidden();
160
			});
161
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
162
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
163
		}
164
	}
165
166
	/**
167
	 * @param \Icewind\SMB\IFileInfo $info
168
	 * @return array
169
	 */
170
	protected function formatInfo($info) {
171
		$result = [
172
			'size' => $info->getSize(),
173
			'mtime' => $info->getMTime(),
174
		];
175
		if ($info->isDirectory()) {
176
			$result['type'] = 'dir';
177
		} else {
178
			$result['type'] = 'file';
179
		}
180
		return $result;
181
	}
182
183
	/**
184
	 * Rename the files. If the source or the target is the root, the rename won't happen.
185
	 *
186
	 * @param string $source the old name of the path
187
	 * @param string $target the new name of the path
188
	 * @return bool true if the rename is successful, false otherwise
189
	 */
190
	public function rename($source, $target) {
191
		if ($this->isRootDir($source) || $this->isRootDir($target)) {
192
			return false;
193
		}
194
195
		$absoluteSource = $this->buildPath($source);
196
		$absoluteTarget = $this->buildPath($target);
197
		try {
198
			$result = $this->share->rename($absoluteSource, $absoluteTarget);
199
		} catch (AlreadyExistsException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\AlreadyExistsException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
200
			$this->remove($target);
201
			$result = $this->share->rename($absoluteSource, $absoluteTarget);
202
		} catch (\Exception $e) {
203
			\OC::$server->getLogger()->logException($e, ['level' => Util::WARN]);
204
			return false;
205
		}
206
		unset($this->statCache[$absoluteSource], $this->statCache[$absoluteTarget]);
207
		return $result;
208
	}
209
210
	/**
211
	 * @param string $path
212
	 * @return array
213
	 */
214
	public function stat($path) {
215
		$result = $this->formatInfo($this->getFileInfo($path));
216
		if ($this->remoteIsShare() && $this->isRootDir($path)) {
217
			$result['mtime'] = $this->shareMTime();
218
		}
219
		return $result;
220
	}
221
222
	/**
223
	 * get the best guess for the modification time of the share
224
	 *
225
	 * @return int
226
	 */
227
	private function shareMTime() {
228
		$highestMTime = 0;
229
		$files = $this->share->dir($this->root);
230
		foreach ($files as $fileInfo) {
231
			if ($fileInfo->getMTime() > $highestMTime) {
232
				$highestMTime = $fileInfo->getMTime();
233
			}
234
		}
235
		return $highestMTime;
236
	}
237
238
	/**
239
	 * Check if the path is our root dir (not the smb one)
240
	 *
241
	 * @param string $path the path
242
	 * @return bool
243
	 */
244
	private function isRootDir($path) {
245
		return $path === '' || $path === '/' || $path === '.';
246
	}
247
248
	/**
249
	 * Check if our root points to a smb share
250
	 *
251
	 * @return bool true if our root points to a share false otherwise
252
	 */
253
	private function remoteIsShare() {
254
		return $this->share->getName() && (!$this->root || $this->root === '/');
255
	}
256
257
	/**
258
	 * @param string $path
259
	 * @return bool
260
	 */
261
	public function unlink($path) {
262
		if ($this->isRootDir($path)) {
263
			return false;
264
		}
265
266
		try {
267
			if ($this->is_dir($path)) {
268
				return $this->rmdir($path);
269
			} else {
270
				$path = $this->buildPath($path);
271
				unset($this->statCache[$path]);
272
				$this->share->del($path);
273
				return true;
274
			}
275
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
276
			return false;
277
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
278
			return false;
279
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
280
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
281
		}
282
	}
283
284
	/**
285
	 * check if a file or folder has been updated since $time
286
	 *
287
	 * @param string $path
288
	 * @param int $time
289
	 * @return bool
290
	 */
291
	public function hasUpdated($path, $time) {
292
		if (!$path and $this->root === '/') {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
293
			// mtime doesn't work for shares, but giving the nature of the backend,
294
			// doing a full update is still just fast enough
295
			return true;
296
		} else {
297
			$actualTime = $this->filemtime($path);
298
			return $actualTime > $time;
299
		}
300
	}
301
302
	/**
303
	 * @param string $path
304
	 * @param string $mode
305
	 * @return resource|false
306
	 */
307
	public function fopen($path, $mode) {
308
		$fullPath = $this->buildPath($path);
309
		try {
310
			switch ($mode) {
311
				case 'r':
312
				case 'rb':
313
					if (!$this->file_exists($path)) {
314
						return false;
315
					}
316
					return $this->share->read($fullPath);
317
				case 'w':
318
				case 'wb':
319
					$source = $this->share->write($fullPath);
320
					return CallBackWrapper::wrap($source, null, null, function () use ($fullPath) {
321
						unset($this->statCache[$fullPath]);
322
					});
323
				case 'a':
324
				case 'ab':
325
				case 'r+':
326
				case 'w+':
327
				case 'wb+':
328
				case 'a+':
329
				case 'x':
330
				case 'x+':
331
				case 'c':
332
				case 'c+':
333
					//emulate these
334
					if (strrpos($path, '.') !== false) {
335
						$ext = substr($path, strrpos($path, '.'));
336
					} else {
337
						$ext = '';
338
					}
339 View Code Duplication
					if ($this->file_exists($path)) {
340
						if (!$this->isUpdatable($path)) {
341
							return false;
342
						}
343
						$tmpFile = $this->getCachedFile($path);
344
					} else {
345
						if (!$this->isCreatable(dirname($path))) {
346
							return false;
347
						}
348
						$tmpFile = \OCP\Files::tmpFile($ext);
349
					}
350
					$source = fopen($tmpFile, $mode);
351
					$share = $this->share;
352
					return CallbackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath, $share) {
353
						unset($this->statCache[$fullPath]);
354
						$share->put($tmpFile, $fullPath);
355
						unlink($tmpFile);
356
					});
357
			}
358
			return false;
359
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
360
			return false;
361
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
362
			return false;
363
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
364
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
365
		}
366
	}
367
368
	public function rmdir($path) {
369
		if ($this->isRootDir($path)) {
370
			return false;
371
		}
372
373
		try {
374
			$this->statCache = array();
375
			$content = $this->share->dir($this->buildPath($path));
376
			foreach ($content as $file) {
377
				if ($file->isDirectory()) {
378
					$this->rmdir($path . '/' . $file->getName());
379
				} else {
380
					$this->share->del($file->getPath());
381
				}
382
			}
383
			$this->share->rmdir($this->buildPath($path));
384
			return true;
385
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
386
			return false;
387
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
388
			return false;
389
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
390
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
391
		}
392
	}
393
394 View Code Duplication
	public function touch($path, $time = null) {
395
		try {
396
			if (!$this->file_exists($path)) {
397
				$fh = $this->share->write($this->buildPath($path));
398
				fclose($fh);
399
				return true;
400
			}
401
			return false;
402
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
403
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
404
		}
405
	}
406
407
	public function opendir($path) {
408
		try {
409
			$files = $this->getFolderContents($path);
410
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
411
			return false;
412
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
413
			return false;
414
		}
415
		$names = array_map(function ($info) {
416
			/** @var \Icewind\SMB\IFileInfo $info */
417
			return $info->getName();
418
		}, $files);
419
		return IteratorDirectory::wrap($names);
420
	}
421
422
	public function filetype($path) {
423
		try {
424
			return $this->getFileInfo($path)->isDirectory() ? 'dir' : 'file';
425
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
426
			return false;
427
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
428
			return false;
429
		}
430
	}
431
432 View Code Duplication
	public function mkdir($path) {
433
		$path = $this->buildPath($path);
434
		try {
435
			$this->share->mkdir($path);
436
			return true;
437
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
438
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
439
		} catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
440
			return false;
441
		}
442
	}
443
444
	public function file_exists($path) {
445
		try {
446
			$this->getFileInfo($path);
447
			return true;
448
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
449
			return false;
450
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
451
			return false;
452
		} catch (ConnectException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ConnectException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
453
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
454
		}
455
	}
456
457 View Code Duplication
	public function isReadable($path) {
458
		try {
459
			$info = $this->getFileInfo($path);
460
			return !$info->isHidden();
461
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
462
			return false;
463
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
464
			return false;
465
		}
466
	}
467
468 View Code Duplication
	public function isUpdatable($path) {
469
		try {
470
			$info = $this->getFileInfo($path);
471
			// following windows behaviour for read-only folders: they can be written into
472
			// (https://support.microsoft.com/en-us/kb/326549 - "cause" section)
473
			return !$info->isHidden() && (!$info->isReadOnly() || $this->is_dir($path));
474
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
475
			return false;
476
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
477
			return false;
478
		}
479
	}
480
481 View Code Duplication
	public function isDeletable($path) {
482
		try {
483
			$info = $this->getFileInfo($path);
484
			return !$info->isHidden() && !$info->isReadOnly();
485
		} catch (NotFoundException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\NotFoundException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
486
			return false;
487
		} catch (ForbiddenException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\ForbiddenException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
488
			return false;
489
		}
490
	}
491
492
	/**
493
	 * check if smbclient is installed
494
	 */
495
	public static function checkDependencies() {
496
		return (
497
			(bool)\OC_Helper::findBinaryPath('smbclient')
498
			|| Server::NativeAvailable()
499
		) ? true : ['smbclient'];
500
	}
501
502
	/**
503
	 * Test a storage for availability
504
	 *
505
	 * @return bool
506
	 */
507
	public function test() {
508
		try {
509
			return parent::test();
510
		} catch (Exception $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
511
			return false;
512
		}
513
	}
514
515
	public function listen($path, callable $callback) {
516
		$this->notify($path)->listen(function (IChange $change) use ($callback) {
517
			if ($change instanceof IRenameChange) {
518
				return $callback($change->getType(), $change->getPath(), $change->getTargetPath());
519
			} else {
520
				return $callback($change->getType(), $change->getPath());
521
			}
522
		});
523
	}
524
525
	public function notify($path) {
526
		$path = '/' . ltrim($path, '/');
527
		$shareNotifyHandler = $this->share->notify($this->buildPath($path));
528
		return new SMBNotifyHandler($shareNotifyHandler, $this->root);
529
	}
530
}
531