Completed
Push — master ( 9aef75...511056 )
by Lukas
17:50 queued 10:35
created

SMB::relativePath()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
				$this->root = '/' . $this->root;
83
			}
84
			if (substr($this->root, -1, 1) != '/') {
85
				$this->root .= '/';
86
			}
87
		} else {
88
			throw new \Exception('Invalid configuration');
89
		}
90
		$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...
91
	}
92
93
	/**
94
	 * @return string
95
	 */
96
	public function getId() {
97
		// FIXME: double slash to keep compatible with the old storage ids,
98
		// failure to do so will lead to creation of a new storage id and
99
		// loss of shares from the storage
100
		return 'smb::' . $this->server->getUser() . '@' . $this->server->getHost() . '//' . $this->share->getName() . '/' . $this->root;
101
	}
102
103
	/**
104
	 * @param string $path
105
	 * @return string
106
	 */
107
	protected function buildPath($path) {
108
		return Filesystem::normalizePath($this->root . '/' . $path, true, false, true);
109
	}
110
111
	protected function relativePath($fullPath) {
112
		if ($fullPath === $this->root) {
113
			return '';
114
		} else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
115
			return substr($fullPath, strlen($this->root));
116
		} else {
117
			return null;
118
		}
119
	}
120
121
	/**
122
	 * @param string $path
123
	 * @return \Icewind\SMB\IFileInfo
124
	 * @throws StorageNotAvailableException
125
	 */
126
	protected function getFileInfo($path) {
127
		try {
128
			$path = $this->buildPath($path);
129
			if (!isset($this->statCache[$path])) {
130
				$this->statCache[$path] = $this->share->stat($path);
131
			}
132
			return $this->statCache[$path];
133
		} 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...
134
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
135
		}
136
	}
137
138
	/**
139
	 * @param string $path
140
	 * @return \Icewind\SMB\IFileInfo[]
141
	 * @throws StorageNotAvailableException
142
	 */
143
	protected function getFolderContents($path) {
144
		try {
145
			$path = $this->buildPath($path);
146
			$files = $this->share->dir($path);
147
			foreach ($files as $file) {
148
				$this->statCache[$path . '/' . $file->getName()] = $file;
149
			}
150
			return array_filter($files, function(IFileInfo $file) {
151
				return !$file->isHidden();
152
			});
153
		} 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...
154
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
155
		}
156
	}
157
158
	/**
159
	 * @param \Icewind\SMB\IFileInfo $info
160
	 * @return array
161
	 */
162
	protected function formatInfo($info) {
163
		return array(
164
			'size' => $info->getSize(),
165
			'mtime' => $info->getMTime()
166
		);
167
	}
168
169
	/**
170
	 * @param string $path
171
	 * @return array
172
	 */
173
	public function stat($path) {
174
		$result = $this->formatInfo($this->getFileInfo($path));
175
		if ($this->remoteIsShare() && $this->isRootDir($path)) {
176
			$result['mtime'] = $this->shareMTime();
177
		}
178
		return $result;
179
	}
180
181
	/**
182
	 * get the best guess for the modification time of the share
183
	 *
184
	 * @return int
185
	 */
186
	private function shareMTime() {
187
		$highestMTime = 0;
188
		$files = $this->share->dir($this->root);
189
		foreach ($files as $fileInfo) {
190
			if ($fileInfo->getMTime() > $highestMTime) {
191
				$highestMTime = $fileInfo->getMTime();
192
			}
193
		}
194
		return $highestMTime;
195
	}
196
197
	/**
198
	 * Check if the path is our root dir (not the smb one)
199
	 *
200
	 * @param string $path the path
201
	 * @return bool
202
	 */
203
	private function isRootDir($path) {
204
		return $path === '' || $path === '/' || $path === '.';
205
	}
206
207
	/**
208
	 * Check if our root points to a smb share
209
	 *
210
	 * @return bool true if our root points to a share false otherwise
211
	 */
212
	private function remoteIsShare() {
213
		return $this->share->getName() && (!$this->root || $this->root === '/');
214
	}
215
216
	/**
217
	 * @param string $path
218
	 * @return bool
219
	 */
220
	public function unlink($path) {
221
		try {
222
			if ($this->is_dir($path)) {
223
				return $this->rmdir($path);
224
			} else {
225
				$path = $this->buildPath($path);
226
				unset($this->statCache[$path]);
227
				$this->share->del($path);
228
				return true;
229
			}
230
		} 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...
231
			return false;
232
		} 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...
233
			return false;
234
		} 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...
235
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
236
		}
237
	}
238
239
	/**
240
	 * @param string $path1 the old name
241
	 * @param string $path2 the new name
242
	 * @return bool
243
	 */
244
	public function rename($path1, $path2) {
245
		try {
246
			$this->remove($path2);
247
			$path1 = $this->buildPath($path1);
248
			$path2 = $this->buildPath($path2);
249
			return $this->share->rename($path1, $path2);
250
		} 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...
251
			return false;
252
		} 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...
253
			return false;
254
		} 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...
255
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
256
		}
257
	}
258
259
	/**
260
	 * check if a file or folder has been updated since $time
261
	 *
262
	 * @param string $path
263
	 * @param int $time
264
	 * @return bool
265
	 */
266
	public function hasUpdated($path, $time) {
267
		if (!$path and $this->root == '/') {
268
			// mtime doesn't work for shares, but giving the nature of the backend,
269
			// doing a full update is still just fast enough
270
			return true;
271
		} else {
272
			$actualTime = $this->filemtime($path);
273
			return $actualTime > $time;
274
		}
275
	}
276
277
	/**
278
	 * @param string $path
279
	 * @param string $mode
280
	 * @return resource|false
281
	 */
282
	public function fopen($path, $mode) {
283
		$fullPath = $this->buildPath($path);
284
		try {
285
			switch ($mode) {
286
				case 'r':
287
				case 'rb':
288
					if (!$this->file_exists($path)) {
289
						return false;
290
					}
291
					return $this->share->read($fullPath);
292
				case 'w':
293
				case 'wb':
294
					$source = $this->share->write($fullPath);
295
					return CallBackWrapper::wrap($source, null, null, function () use ($fullPath) {
296
						unset($this->statCache[$fullPath]);
297
					});
298
				case 'a':
299
				case 'ab':
300
				case 'r+':
301
				case 'w+':
302
				case 'wb+':
303
				case 'a+':
304
				case 'x':
305
				case 'x+':
306
				case 'c':
307
				case 'c+':
308
					//emulate these
309
					if (strrpos($path, '.') !== false) {
310
						$ext = substr($path, strrpos($path, '.'));
311
					} else {
312
						$ext = '';
313
					}
314 View Code Duplication
					if ($this->file_exists($path)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
315
						if (!$this->isUpdatable($path)) {
316
							return false;
317
						}
318
						$tmpFile = $this->getCachedFile($path);
319
					} else {
320
						if (!$this->isCreatable(dirname($path))) {
321
							return false;
322
						}
323
						$tmpFile = \OCP\Files::tmpFile($ext);
0 ignored issues
show
Deprecated Code introduced by
The method OCP\Files::tmpFile() has been deprecated with message: 8.1.0 use getTemporaryFile() of \OCP\ITempManager - \OC::$server->getTempManager()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
324
					}
325
					$source = fopen($tmpFile, $mode);
326
					$share = $this->share;
327
					return CallbackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath, $share) {
328
						unset($this->statCache[$fullPath]);
329
						$share->put($tmpFile, $fullPath);
330
						unlink($tmpFile);
331
					});
332
			}
333
			return false;
334
		} 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...
335
			return false;
336
		} 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...
337
			return false;
338
		} 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...
339
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
340
		}
341
	}
342
343
	public function rmdir($path) {
344
		try {
345
			$this->statCache = array();
346
			$content = $this->share->dir($this->buildPath($path));
347
			foreach ($content as $file) {
348
				if ($file->isDirectory()) {
349
					$this->rmdir($path . '/' . $file->getName());
350
				} else {
351
					$this->share->del($file->getPath());
352
				}
353
			}
354
			$this->share->rmdir($this->buildPath($path));
355
			return true;
356
		} 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...
357
			return false;
358
		} 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...
359
			return false;
360
		} 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...
361
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
362
		}
363
	}
364
365 View Code Duplication
	public function touch($path, $time = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
366
		try {
367
			if (!$this->file_exists($path)) {
368
				$fh = $this->share->write($this->buildPath($path));
369
				fclose($fh);
370
				return true;
371
			}
372
			return false;
373
		} 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...
374
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
375
		}
376
	}
377
378
	public function opendir($path) {
379
		try {
380
			$files = $this->getFolderContents($path);
381
		} 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...
382
			return false;
383
		} 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...
384
			return false;
385
		}
386
		$names = array_map(function ($info) {
387
			/** @var \Icewind\SMB\IFileInfo $info */
388
			return $info->getName();
389
		}, $files);
390
		return IteratorDirectory::wrap($names);
391
	}
392
393
	public function filetype($path) {
394
		try {
395
			return $this->getFileInfo($path)->isDirectory() ? 'dir' : 'file';
396
		} 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...
397
			return false;
398
		} 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...
399
			return false;
400
		}
401
	}
402
403 View Code Duplication
	public function mkdir($path) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
404
		$path = $this->buildPath($path);
405
		try {
406
			$this->share->mkdir($path);
407
			return true;
408
		} 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...
409
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
410
		} 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...
411
			return false;
412
		}
413
	}
414
415
	public function file_exists($path) {
416
		try {
417
			$this->getFileInfo($path);
418
			return true;
419
		} 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...
420
			return false;
421
		} 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...
422
			return false;
423
		} 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...
424
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
425
		}
426
	}
427
428 View Code Duplication
	public function isReadable($path) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
429
		try {
430
			$info = $this->getFileInfo($path);
431
			return !$info->isHidden();
432
		} 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...
433
			return false;
434
		} 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...
435
			return false;
436
		}
437
	}
438
439 View Code Duplication
	public function isUpdatable($path) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
440
		try {
441
			$info = $this->getFileInfo($path);
442
			// following windows behaviour for read-only folders: they can be written into
443
			// (https://support.microsoft.com/en-us/kb/326549 - "cause" section)
444
			return !$info->isHidden() && (!$info->isReadOnly() || $this->is_dir($path));
445
		} 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...
446
			return false;
447
		} 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...
448
			return false;
449
		}
450
	}
451
452 View Code Duplication
	public function isDeletable($path) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
453
		try {
454
			$info = $this->getFileInfo($path);
455
			return !$info->isHidden() && !$info->isReadOnly();
456
		} 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...
457
			return false;
458
		} 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...
459
			return false;
460
		}
461
	}
462
463
	/**
464
	 * check if smbclient is installed
465
	 */
466
	public static function checkDependencies() {
467
		return (
468
			(bool)\OC_Helper::findBinaryPath('smbclient')
469
			|| Server::NativeAvailable()
470
		) ? true : ['smbclient'];
471
	}
472
473
	/**
474
	 * Test a storage for availability
475
	 *
476
	 * @return bool
477
	 */
478
	public function test() {
479
		try {
480
			return parent::test();
481
		} 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...
482
			return false;
483
		}
484
	}
485
486
	public function listen($path, callable $callback) {
487
		$fullPath = $this->buildPath($path);
488
		$oldRenamePath = null;
489
		$this->share->notify($fullPath, function ($smbType, $fullPath) use (&$oldRenamePath, $callback) {
490
			$path = $this->relativePath($fullPath);
491
			if (is_null($path)) {
492
				return true;
493
			}
494
			if ($smbType === IShare::NOTIFY_RENAMED_OLD) {
495
				$oldRenamePath = $path;
496
				return true;
497
			}
498
			$type = $this->mapNotifyType($smbType);
499
			if (is_null($type)) {
500
				return true;
501
			}
502
			if ($type === INotifyStorage::NOTIFY_RENAMED && !is_null($oldRenamePath)) {
503
				$result = $callback($type, $path, $oldRenamePath);
504
				$oldRenamePath = null;
505
			} else {
506
				$result = $callback($type, $path);
507
			}
508
			return $result;
509
		});
510
	}
511
512
	private function mapNotifyType($smbType) {
513
		switch ($smbType) {
514
			case IShare::NOTIFY_ADDED:
515
				return INotifyStorage::NOTIFY_ADDED;
516
			case IShare::NOTIFY_REMOVED:
517
				return INotifyStorage::NOTIFY_REMOVED;
518
			case IShare::NOTIFY_MODIFIED:
519
			case IShare::NOTIFY_ADDED_STREAM:
520
			case IShare::NOTIFY_MODIFIED_STREAM:
521
			case IShare::NOTIFY_REMOVED_STREAM:
522
				return INotifyStorage::NOTIFY_MODIFIED;
523
			case IShare::NOTIFY_RENAMED_NEW:
524
				return INotifyStorage::NOTIFY_RENAMED;
525
			default:
526
				return null;
527
		}
528
	}
529
}
530