Completed
Push — stable13 ( 389b98...394079 )
by Morris
20:43
created

SMB::stat()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 6
nop 2
dl 0
loc 19
rs 8.8333
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\InvalidArgumentException;
42
use Icewind\SMB\Exception\NotFoundException;
43
use Icewind\SMB\Exception\TimedOutException;
44
use Icewind\SMB\IFileInfo;
45
use Icewind\SMB\NativeServer;
46
use Icewind\SMB\Server;
47
use Icewind\Streams\CallbackWrapper;
48
use Icewind\Streams\IteratorDirectory;
49
use OC\Cache\CappedMemoryCache;
50
use OC\Files\Filesystem;
51
use OC\Files\Storage\Common;
52
use OCA\Files_External\Lib\Notify\SMBNotifyHandler;
53
use OCP\Files\Notify\IChange;
54
use OCP\Files\Notify\IRenameChange;
55
use OCP\Files\Storage\INotifyStorage;
56
use OCP\Files\StorageNotAvailableException;
57
use OCP\ILogger;
58
use OCP\Util;
59
60
class SMB extends Common implements INotifyStorage {
61
	/**
62
	 * @var \Icewind\SMB\Server
63
	 */
64
	protected $server;
65
66
	/**
67
	 * @var \Icewind\SMB\Share
68
	 */
69
	protected $share;
70
71
	/**
72
	 * @var string
73
	 */
74
	protected $root;
75
76
	/**
77
	 * @var \Icewind\SMB\FileInfo[]
78
	 */
79
	protected $statCache;
80
81
	public function __construct($params) {
82
		if (isset($params['host']) && isset($params['user']) && isset($params['password']) && isset($params['share'])) {
83
			if (Server::NativeAvailable()) {
84
				$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...
85
			} else {
86
				$this->server = new Server($params['host'], $params['user'], $params['password']);
87
			}
88
			$this->share = $this->server->getShare(trim($params['share'], '/'));
89
90
			$this->root = isset($params['root']) ? $params['root'] : '/';
91 View Code Duplication
			if (!$this->root || $this->root[0] !== '/') {
92
				$this->root = '/' . $this->root;
93
			}
94
			if (substr($this->root, -1, 1) !== '/') {
95
				$this->root .= '/';
96
			}
97
		} else {
98
			throw new \Exception('Invalid configuration');
99
		}
100
		$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...
101
		parent::__construct($params);
102
	}
103
104
	/**
105
	 * @return string
106
	 */
107
	public function getId() {
108
		// FIXME: double slash to keep compatible with the old storage ids,
109
		// failure to do so will lead to creation of a new storage id and
110
		// loss of shares from the storage
111
		return 'smb::' . $this->server->getUser() . '@' . $this->server->getHost() . '//' . $this->share->getName() . '/' . $this->root;
112
	}
113
114
	/**
115
	 * @param string $path
116
	 * @return string
117
	 */
118
	protected function buildPath($path) {
119
		return Filesystem::normalizePath($this->root . '/' . $path, true, false, true);
120
	}
121
122 View Code Duplication
	protected function relativePath($fullPath) {
123
		if ($fullPath === $this->root) {
124
			return '';
125
		} else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
126
			return substr($fullPath, strlen($this->root));
127
		} else {
128
			return null;
129
		}
130
	}
131
132
	/**
133
	 * @param string $path
134
	 * @return \Icewind\SMB\IFileInfo
135
	 * @throws StorageNotAvailableException
136
	 */
137
	protected function getFileInfo($path) {
138
		try {
139
			$path = $this->buildPath($path);
140
			if (!isset($this->statCache[$path])) {
141
				$this->statCache[$path] = $this->share->stat($path);
142
			}
143
			return $this->statCache[$path];
144
		} 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...
145
			\OC::$server->getLogger()->logException($e, ['message' => 'Error while getting file info']);
146
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
147
		}
148
	}
149
150
	/**
151
	 * @param string $path
152
	 * @return \Icewind\SMB\IFileInfo[]
153
	 * @throws StorageNotAvailableException
154
	 */
155
	protected function getFolderContents($path) {
156
		try {
157
			$path = $this->buildPath($path);
158
			$files = $this->share->dir($path);
159
			foreach ($files as $file) {
160
				$this->statCache[$path . '/' . $file->getName()] = $file;
161
			}
162
			return array_filter($files, function (IFileInfo $file) {
163
				try {
164
					if ($file->isHidden()) {
165
						\OC::$server->getLogger()->debug('hiding hidden file ' . $file->getName());
166
					}
167
					return !$file->isHidden();
168
				} 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...
169
					\OC::$server->getLogger()->logException($e, ['level' => Util::DEBUG, 'message' => 'Hiding forbidden entry ' . $file->getName()]);
170
					return false;
171
				} 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...
172
					\OC::$server->getLogger()->logException($e, ['level' => Util::DEBUG, 'message' => 'Hiding not found entry ' . $file->getName()]);
173
					return false;
174
				}
175
			});
176
		} 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...
177
			\OC::$server->getLogger()->logException($e, ['message' => 'Error while getting folder content']);
178
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
179
		}
180
	}
181
182
	/**
183
	 * @param \Icewind\SMB\IFileInfo $info
184
	 * @return array
185
	 */
186
	protected function formatInfo($info) {
187
		$result = [
188
			'size' => $info->getSize(),
189
			'mtime' => $info->getMTime(),
190
		];
191
		if ($info->isDirectory()) {
192
			$result['type'] = 'dir';
193
		} else {
194
			$result['type'] = 'file';
195
		}
196
		return $result;
197
	}
198
199
	/**
200
	 * Rename the files. If the source or the target is the root, the rename won't happen.
201
	 *
202
	 * @param string $source the old name of the path
203
	 * @param string $target the new name of the path
204
	 * @return bool true if the rename is successful, false otherwise
205
	 */
206
	public function rename($source, $target, $retry = true) {
207
		if ($this->isRootDir($source) || $this->isRootDir($target)) {
208
			return false;
209
		}
210
211
		$absoluteSource = $this->buildPath($source);
212
		$absoluteTarget = $this->buildPath($target);
213
		try {
214
			$result = $this->share->rename($absoluteSource, $absoluteTarget);
215
		} 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...
216 View Code Duplication
			if ($retry) {
217
				$this->remove($target);
218
				$result = $this->share->rename($absoluteSource, $absoluteTarget, false);
219
			} else {
220
				\OC::$server->getLogger()->logException($e, ['level' => ILogger::WARN]);
221
				return false;
222
			}
223
		} catch (InvalidArgumentException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\InvalidArgumentException 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...
224 View Code Duplication
			if ($retry) {
225
				$this->remove($target);
226
				$result = $this->share->rename($absoluteSource, $absoluteTarget, false);
227
			} else {
228
				\OC::$server->getLogger()->logException($e, ['level' => ILogger::WARN]);
229
				return false;
230
			}
231
		} catch (\Exception $e) {
232
			\OC::$server->getLogger()->logException($e, ['level' => Util::WARN]);
233
			return false;
234
		}
235
		unset($this->statCache[$absoluteSource], $this->statCache[$absoluteTarget]);
236
		return $result;
237
	}
238
239
	public function stat($path, $retry = true) {
240
		try {
241
			$result = $this->formatInfo($this->getFileInfo($path));
242
		} 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...
243
			return false;
244
		} 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...
245
			return false;
246
		} catch (TimedOutException $e) {
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\Exception\TimedOutException 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...
247
			if ($retry) {
248
				return $this->stat($path, false);
249
			} else {
250
				throw $e;
251
			}
252
		}
253
		if ($this->remoteIsShare() && $this->isRootDir($path)) {
254
			$result['mtime'] = $this->shareMTime();
255
		}
256
		return $result;
257
	}
258
259
	/**
260
	 * get the best guess for the modification time of the share
261
	 *
262
	 * @return int
263
	 */
264
	private function shareMTime() {
265
		$highestMTime = 0;
266
		$files = $this->share->dir($this->root);
267
		foreach ($files as $fileInfo) {
268
			try {
269
				if ($fileInfo->getMTime() > $highestMTime) {
270
					$highestMTime = $fileInfo->getMTime();
271
				}
272
			} 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...
273
				// Ignore this, can happen on unavailable DFS shares
274
			}
275
		}
276
		return $highestMTime;
277
	}
278
279
	/**
280
	 * Check if the path is our root dir (not the smb one)
281
	 *
282
	 * @param string $path the path
283
	 * @return bool
284
	 */
285
	private function isRootDir($path) {
286
		return $path === '' || $path === '/' || $path === '.';
287
	}
288
289
	/**
290
	 * Check if our root points to a smb share
291
	 *
292
	 * @return bool true if our root points to a share false otherwise
293
	 */
294
	private function remoteIsShare() {
295
		return $this->share->getName() && (!$this->root || $this->root === '/');
296
	}
297
298
	/**
299
	 * @param string $path
300
	 * @return bool
301
	 */
302
	public function unlink($path) {
303
		if ($this->isRootDir($path)) {
304
			return false;
305
		}
306
307
		try {
308
			if ($this->is_dir($path)) {
309
				return $this->rmdir($path);
310
			} else {
311
				$path = $this->buildPath($path);
312
				unset($this->statCache[$path]);
313
				$this->share->del($path);
314
				return true;
315
			}
316
		} 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...
317
			return false;
318
		} 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...
319
			return false;
320
		} 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...
321
			\OC::$server->getLogger()->logException($e, ['message' => 'Error while deleting file']);
322
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
323
		}
324
	}
325
326
	/**
327
	 * check if a file or folder has been updated since $time
328
	 *
329
	 * @param string $path
330
	 * @param int $time
331
	 * @return bool
332
	 */
333
	public function hasUpdated($path, $time) {
334
		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...
335
			// mtime doesn't work for shares, but giving the nature of the backend,
336
			// doing a full update is still just fast enough
337
			return true;
338
		} else {
339
			$actualTime = $this->filemtime($path);
340
			return $actualTime > $time;
341
		}
342
	}
343
344
	/**
345
	 * @param string $path
346
	 * @param string $mode
347
	 * @return resource|false
348
	 */
349
	public function fopen($path, $mode) {
350
		$fullPath = $this->buildPath($path);
351
		try {
352
			switch ($mode) {
353
				case 'r':
354
				case 'rb':
355
					if (!$this->file_exists($path)) {
356
						return false;
357
					}
358
					return $this->share->read($fullPath);
359
				case 'w':
360
				case 'wb':
361
					$source = $this->share->write($fullPath);
362
					return CallBackWrapper::wrap($source, null, null, function () use ($fullPath) {
363
						unset($this->statCache[$fullPath]);
364
					});
365
				case 'a':
366
				case 'ab':
367
				case 'r+':
368
				case 'w+':
369
				case 'wb+':
370
				case 'a+':
371
				case 'x':
372
				case 'x+':
373
				case 'c':
374
				case 'c+':
375
					//emulate these
376
					if (strrpos($path, '.') !== false) {
377
						$ext = substr($path, strrpos($path, '.'));
378
					} else {
379
						$ext = '';
380
					}
381 View Code Duplication
					if ($this->file_exists($path)) {
382
						if (!$this->isUpdatable($path)) {
383
							return false;
384
						}
385
						$tmpFile = $this->getCachedFile($path);
386
					} else {
387
						if (!$this->isCreatable(dirname($path))) {
388
							return false;
389
						}
390
						$tmpFile = \OCP\Files::tmpFile($ext);
391
					}
392
					$source = fopen($tmpFile, $mode);
393
					$share = $this->share;
394
					return CallbackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath, $share) {
395
						unset($this->statCache[$fullPath]);
396
						$share->put($tmpFile, $fullPath);
397
						unlink($tmpFile);
398
					});
399
			}
400
			return false;
401
		} 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...
402
			return false;
403
		} 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...
404
			return false;
405
		} 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...
406
			\OC::$server->getLogger()->logException($e, ['message' => 'Error while opening file']);
407
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
408
		}
409
	}
410
411
	public function rmdir($path) {
412
		if ($this->isRootDir($path)) {
413
			return false;
414
		}
415
416
		try {
417
			$this->statCache = array();
418
			$content = $this->share->dir($this->buildPath($path));
419
			foreach ($content as $file) {
420
				if ($file->isDirectory()) {
421
					$this->rmdir($path . '/' . $file->getName());
422
				} else {
423
					$this->share->del($file->getPath());
424
				}
425
			}
426
			$this->share->rmdir($this->buildPath($path));
427
			return true;
428
		} 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...
429
			return false;
430
		} 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...
431
			return false;
432
		} 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...
433
			\OC::$server->getLogger()->logException($e, ['message' => 'Error while removing folder']);
434
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
435
		}
436
	}
437
438 View Code Duplication
	public function touch($path, $time = null) {
439
		try {
440
			if (!$this->file_exists($path)) {
441
				$fh = $this->share->write($this->buildPath($path));
442
				fclose($fh);
443
				return true;
444
			}
445
			return false;
446
		} 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...
447
			\OC::$server->getLogger()->logException($e, ['message' => 'Error while creating file']);
448
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
449
		}
450
	}
451
452
	public function opendir($path) {
453
		try {
454
			$files = $this->getFolderContents($path);
455
		} 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...
456
			return false;
457
		} 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...
458
			return false;
459
		}
460
		$names = array_map(function ($info) {
461
			/** @var \Icewind\SMB\IFileInfo $info */
462
			return $info->getName();
463
		}, $files);
464
		return IteratorDirectory::wrap($names);
465
	}
466
467
	public function filetype($path) {
468
		try {
469
			return $this->getFileInfo($path)->isDirectory() ? 'dir' : 'file';
470
		} 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...
471
			return false;
472
		} 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...
473
			return false;
474
		}
475
	}
476
477 View Code Duplication
	public function mkdir($path) {
478
		$path = $this->buildPath($path);
479
		try {
480
			$this->share->mkdir($path);
481
			return true;
482
		} 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...
483
			\OC::$server->getLogger()->logException($e, ['message' => 'Error while creating folder']);
484
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
485
		} 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...
486
			return false;
487
		}
488
	}
489
490
	public function file_exists($path) {
491
		try {
492
			$this->getFileInfo($path);
493
			return true;
494
		} 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...
495
			return false;
496
		} 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...
497
			return false;
498
		} 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...
499
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
500
		}
501
	}
502
503 View Code Duplication
	public function isReadable($path) {
504
		try {
505
			$info = $this->getFileInfo($path);
506
			return !$info->isHidden();
507
		} 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...
508
			return false;
509
		} 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...
510
			return false;
511
		}
512
	}
513
514 View Code Duplication
	public function isUpdatable($path) {
515
		try {
516
			$info = $this->getFileInfo($path);
517
			// following windows behaviour for read-only folders: they can be written into
518
			// (https://support.microsoft.com/en-us/kb/326549 - "cause" section)
519
			return !$info->isHidden() && (!$info->isReadOnly() || $this->is_dir($path));
520
		} 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...
521
			return false;
522
		} 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...
523
			return false;
524
		}
525
	}
526
527 View Code Duplication
	public function isDeletable($path) {
528
		try {
529
			$info = $this->getFileInfo($path);
530
			return !$info->isHidden() && !$info->isReadOnly();
531
		} 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...
532
			return false;
533
		} 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...
534
			return false;
535
		}
536
	}
537
538
	/**
539
	 * check if smbclient is installed
540
	 */
541
	public static function checkDependencies() {
542
		return (
543
			(bool)\OC_Helper::findBinaryPath('smbclient')
544
			|| Server::NativeAvailable()
545
		) ? true : ['smbclient'];
546
	}
547
548
	/**
549
	 * Test a storage for availability
550
	 *
551
	 * @return bool
552
	 */
553
	public function test() {
554
		try {
555
			return parent::test();
556
		} 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...
557
			\OC::$server->getLogger()->logException($e);
558
			return false;
559
		}
560
	}
561
562
	public function listen($path, callable $callback) {
563
		$this->notify($path)->listen(function (IChange $change) use ($callback) {
564
			if ($change instanceof IRenameChange) {
565
				return $callback($change->getType(), $change->getPath(), $change->getTargetPath());
566
			} else {
567
				return $callback($change->getType(), $change->getPath());
568
			}
569
		});
570
	}
571
572
	public function notify($path) {
573
		$path = '/' . ltrim($path, '/');
574
		$shareNotifyHandler = $this->share->notify($this->buildPath($path));
575
		return new SMBNotifyHandler($shareNotifyHandler, $this->root);
576
	}
577
}
578