Completed
Push — stable10 ( 6888de...94d9d5 )
by Lukas
09:12
created

SMB::isUpdatable()   B

Complexity

Conditions 5
Paths 11

Size

Total Lines 12
Code Lines 8

Duplication

Lines 12
Ratio 100 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 5
eloc 8
c 1
b 1
f 0
nc 11
nop 1
dl 12
loc 12
rs 8.8571
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\IShare;
39
use Icewind\SMB\NativeServer;
40
use Icewind\SMB\Server;
41
use Icewind\Streams\CallbackWrapper;
42
use Icewind\Streams\IteratorDirectory;
43
use OC\Cache\CappedMemoryCache;
44
use OC\Files\Filesystem;
45
use OC\Files\Storage\Common;
46
use OCP\Files\Storage\INotifyStorage;
47
use OCP\Files\StorageNotAvailableException;
48
49
class SMB extends Common implements INotifyStorage {
50
	/**
51
	 * @var \Icewind\SMB\Server
52
	 */
53
	protected $server;
54
55
	/**
56
	 * @var \Icewind\SMB\Share
57
	 */
58
	protected $share;
59
60
	/**
61
	 * @var string
62
	 */
63
	protected $root;
64
65
	/**
66
	 * @var \Icewind\SMB\FileInfo[]
67
	 */
68
	protected $statCache;
69
70
	public function __construct($params) {
71
		if (isset($params['host']) && isset($params['user']) && isset($params['password']) && isset($params['share'])) {
72
			if (Server::NativeAvailable()) {
73
				$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...
74
			} else {
75
				$this->server = new Server($params['host'], $params['user'], $params['password']);
76
			}
77
			$this->share = $this->server->getShare(trim($params['share'], '/'));
78
79
			$this->root = isset($params['root']) ? $params['root'] : '/';
80 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...
81
				$this->root = '/' . $this->root;
82
			}
83
			if (substr($this->root, -1, 1) != '/') {
84
				$this->root .= '/';
85
			}
86
		} else {
87
			throw new \Exception('Invalid configuration');
88
		}
89
		$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...
90
	}
91
92
	/**
93
	 * @return string
94
	 */
95
	public function getId() {
96
		// FIXME: double slash to keep compatible with the old storage ids,
97
		// failure to do so will lead to creation of a new storage id and
98
		// loss of shares from the storage
99
		return 'smb::' . $this->server->getUser() . '@' . $this->server->getHost() . '//' . $this->share->getName() . '/' . $this->root;
100
	}
101
102
	/**
103
	 * @param string $path
104
	 * @return string
105
	 */
106
	protected function buildPath($path) {
107
		return Filesystem::normalizePath($this->root . '/' . $path, true, false, true);
108
	}
109
110
	protected function relativePath($fullPath) {
111
		if ($fullPath === $this->root) {
112
			return '';
113
		} else if (substr($fullPath, 0, strlen($this->root)) === $this->root) {
114
			return substr($fullPath, strlen($this->root));
115
		} else {
116
			return null;
117
		}
118
	}
119
120
	/**
121
	 * @param string $path
122
	 * @return \Icewind\SMB\IFileInfo
123
	 * @throws StorageNotAvailableException
124
	 */
125
	protected function getFileInfo($path) {
126
		try {
127
			$path = $this->buildPath($path);
128
			if (!isset($this->statCache[$path])) {
129
				$this->statCache[$path] = $this->share->stat($path);
130
			}
131
			return $this->statCache[$path];
132
		} 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...
133
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
134
		}
135
	}
136
137
	/**
138
	 * @param string $path
139
	 * @return \Icewind\SMB\IFileInfo[]
140
	 * @throws StorageNotAvailableException
141
	 */
142
	protected function getFolderContents($path) {
143
		try {
144
			$path = $this->buildPath($path);
145
			$files = $this->share->dir($path);
146
			foreach ($files as $file) {
147
				$this->statCache[$path . '/' . $file->getName()] = $file;
148
			}
149
			return $files;
150
		} 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...
151
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
152
		}
153
	}
154
155
	/**
156
	 * @param \Icewind\SMB\IFileInfo $info
157
	 * @return array
158
	 */
159
	protected function formatInfo($info) {
160
		return array(
161
			'size' => $info->getSize(),
162
			'mtime' => $info->getMTime()
163
		);
164
	}
165
166
	/**
167
	 * @param string $path
168
	 * @return array
169
	 */
170
	public function stat($path) {
171
		return $this->formatInfo($this->getFileInfo($path));
172
	}
173
174
	/**
175
	 * @param string $path
176
	 * @return bool
177
	 */
178
	public function unlink($path) {
179
		try {
180
			if ($this->is_dir($path)) {
181
				return $this->rmdir($path);
182
			} else {
183
				$path = $this->buildPath($path);
184
				unset($this->statCache[$path]);
185
				$this->share->del($path);
186
				return true;
187
			}
188
		} 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...
189
			return false;
190
		} 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...
191
			return false;
192
		} 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...
193
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
194
		}
195
	}
196
197
	/**
198
	 * @param string $path1 the old name
199
	 * @param string $path2 the new name
200
	 * @return bool
201
	 */
202
	public function rename($path1, $path2) {
203
		try {
204
			$this->remove($path2);
205
			$path1 = $this->buildPath($path1);
206
			$path2 = $this->buildPath($path2);
207
			return $this->share->rename($path1, $path2);
208
		} 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...
209
			return false;
210
		} 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...
211
			return false;
212
		} 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...
213
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
214
		}
215
	}
216
217
	/**
218
	 * check if a file or folder has been updated since $time
219
	 *
220
	 * @param string $path
221
	 * @param int $time
222
	 * @return bool
223
	 */
224
	public function hasUpdated($path, $time) {
225
		if (!$path and $this->root == '/') {
226
			// mtime doesn't work for shares, but giving the nature of the backend,
227
			// doing a full update is still just fast enough
228
			return true;
229
		} else {
230
			$actualTime = $this->filemtime($path);
231
			return $actualTime > $time;
232
		}
233
	}
234
235
	/**
236
	 * @param string $path
237
	 * @param string $mode
238
	 * @return resource|false
239
	 */
240
	public function fopen($path, $mode) {
241
		$fullPath = $this->buildPath($path);
242
		try {
243
			switch ($mode) {
244
				case 'r':
245
				case 'rb':
246
					if (!$this->file_exists($path)) {
247
						return false;
248
					}
249
					return $this->share->read($fullPath);
250
				case 'w':
251
				case 'wb':
252
					$source = $this->share->write($fullPath);
253
					return CallBackWrapper::wrap($source, null, null, function () use ($fullPath) {
254
						unset($this->statCache[$fullPath]);
255
					});
256
				case 'a':
257
				case 'ab':
258
				case 'r+':
259
				case 'w+':
260
				case 'wb+':
261
				case 'a+':
262
				case 'x':
263
				case 'x+':
264
				case 'c':
265
				case 'c+':
266
					//emulate these
267
					if (strrpos($path, '.') !== false) {
268
						$ext = substr($path, strrpos($path, '.'));
269
					} else {
270
						$ext = '';
271
					}
272 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...
273
						if (!$this->isUpdatable($path)) {
274
							return false;
275
						}
276
						$tmpFile = $this->getCachedFile($path);
277
					} else {
278
						if (!$this->isCreatable(dirname($path))) {
279
							return false;
280
						}
281
						$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...
282
					}
283
					$source = fopen($tmpFile, $mode);
284
					$share = $this->share;
285
					return CallbackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath, $share) {
286
						unset($this->statCache[$fullPath]);
287
						$share->put($tmpFile, $fullPath);
288
						unlink($tmpFile);
289
					});
290
			}
291
			return false;
292
		} 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...
293
			return false;
294
		} 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...
295
			return false;
296
		} 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...
297
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
298
		}
299
	}
300
301
	public function rmdir($path) {
302
		try {
303
			$this->statCache = array();
304
			$content = $this->share->dir($this->buildPath($path));
305
			foreach ($content as $file) {
306
				if ($file->isDirectory()) {
307
					$this->rmdir($path . '/' . $file->getName());
308
				} else {
309
					$this->share->del($file->getPath());
310
				}
311
			}
312
			$this->share->rmdir($this->buildPath($path));
313
			return true;
314
		} 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...
315
			return false;
316
		} 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...
317
			return false;
318
		} 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...
319
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
320
		}
321
	}
322
323 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...
324
		try {
325
			if (!$this->file_exists($path)) {
326
				$fh = $this->share->write($this->buildPath($path));
327
				fclose($fh);
328
				return true;
329
			}
330
			return false;
331
		} 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...
332
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
333
		}
334
	}
335
336
	public function opendir($path) {
337
		try {
338
			$files = $this->getFolderContents($path);
339
		} 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...
340
			return false;
341
		} 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...
342
			return false;
343
		}
344
		$names = array_map(function ($info) {
345
			/** @var \Icewind\SMB\IFileInfo $info */
346
			return $info->getName();
347
		}, $files);
348
		return IteratorDirectory::wrap($names);
349
	}
350
351
	public function filetype($path) {
352
		try {
353
			return $this->getFileInfo($path)->isDirectory() ? 'dir' : 'file';
354
		} 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...
355
			return false;
356
		} 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...
357
			return false;
358
		}
359
	}
360
361 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...
362
		$path = $this->buildPath($path);
363
		try {
364
			$this->share->mkdir($path);
365
			return true;
366
		} 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...
367
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
368
		} 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...
369
			return false;
370
		}
371
	}
372
373
	public function file_exists($path) {
374
		try {
375
			$this->getFileInfo($path);
376
			return true;
377
		} 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...
378
			return false;
379
		} 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...
380
			return false;
381
		} 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...
382
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
383
		}
384
	}
385
386 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...
387
		try {
388
			$info = $this->getFileInfo($path);
389
			return !$info->isHidden();
390
		} 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...
391
			return false;
392
		} 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...
393
			return false;
394
		}
395
	}
396
397 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...
398
		try {
399
			$info = $this->getFileInfo($path);
400
			// following windows behaviour for read-only folders: they can be written into
401
			// (https://support.microsoft.com/en-us/kb/326549 - "cause" section)
402
			return !$info->isHidden() && (!$info->isReadOnly() || $this->is_dir($path));
403
		} 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...
404
			return false;
405
		} 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...
406
			return false;
407
		}
408
	}
409
410 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...
411
		try {
412
			$info = $this->getFileInfo($path);
413
			return !$info->isHidden() && !$info->isReadOnly();
414
		} 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...
415
			return false;
416
		} 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...
417
			return false;
418
		}
419
	}
420
421
	/**
422
	 * check if smbclient is installed
423
	 */
424
	public static function checkDependencies() {
425
		return (
426
			(bool)\OC_Helper::findBinaryPath('smbclient')
427
			|| Server::NativeAvailable()
428
		) ? true : ['smbclient'];
429
	}
430
431
	/**
432
	 * Test a storage for availability
433
	 *
434
	 * @return bool
435
	 */
436
	public function test() {
437
		try {
438
			return parent::test();
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 listen($path, callable $callback) {
445
		$fullPath = $this->buildPath($path);
446
		$oldRenamePath = null;
447
		$this->share->notify($fullPath, function ($smbType, $fullPath) use (&$oldRenamePath, $callback) {
448
			$path = $this->relativePath($fullPath);
449
			if (is_null($path)) {
450
				return true;
451
			}
452
			if ($smbType === IShare::NOTIFY_RENAMED_OLD) {
453
				$oldRenamePath = $path;
454
				return true;
455
			}
456
			$type = $this->mapNotifyType($smbType);
457
			if (is_null($type)) {
458
				return true;
459
			}
460
			if ($type === INotifyStorage::NOTIFY_RENAMED && !is_null($oldRenamePath)) {
461
				$result = $callback($type, $path, $oldRenamePath);
462
				$oldRenamePath = null;
463
			} else {
464
				$result = $callback($type, $path);
465
			}
466
			return $result;
467
		});
468
	}
469
470
	private function mapNotifyType($smbType) {
471
		switch ($smbType) {
472
			case IShare::NOTIFY_ADDED:
473
				return INotifyStorage::NOTIFY_ADDED;
474
			case IShare::NOTIFY_REMOVED:
475
				return INotifyStorage::NOTIFY_REMOVED;
476
			case IShare::NOTIFY_MODIFIED:
477
			case IShare::NOTIFY_ADDED_STREAM:
478
			case IShare::NOTIFY_MODIFIED_STREAM:
479
			case IShare::NOTIFY_REMOVED_STREAM:
480
				return INotifyStorage::NOTIFY_MODIFIED;
481
			case IShare::NOTIFY_RENAMED_NEW:
482
				return INotifyStorage::NOTIFY_RENAMED;
483
			default:
484
				return null;
485
		}
486
	}
487
}
488