Completed
Pull Request — master (#24279)
by Robin
09:47
created

SMB::notify()   C

Complexity

Conditions 8
Paths 2

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

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

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

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

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

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

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

Loading history...
98
	}
99
100
	/**
101
	 * @return string
102
	 */
103
	public function getId() {
104
		// FIXME: double slash to keep compatible with the old storage ids,
105
		// failure to do so will lead to creation of a new storage id and
106
		// loss of shares from the storage
107
		return 'smb::' . $this->server->getUser() . '@' . $this->server->getHost() . '//' . $this->share->getName() . '/' . $this->root;
108
	}
109
110
	/**
111
	 * @param string $path
112
	 * @return string
113
	 */
114
	protected function buildPath($path) {
115
		return Filesystem::normalizePath($this->root . '/' . $path);
116
	}
117
118
	/**
119
	 * @param string $path
120
	 * @return \Icewind\SMB\IFileInfo
121
	 * @throws StorageNotAvailableException
122
	 */
123
	protected function getFileInfo($path) {
124
		try {
125
			$path = $this->buildPath($path);
126
			if (!isset($this->statCache[$path])) {
127
				$this->statCache[$path] = $this->share->stat($path);
128
			}
129
			return $this->statCache[$path];
130
		} catch (ConnectException $e) {
1 ignored issue
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...
131
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
132
		}
133
	}
134
135
	/**
136
	 * @param string $path
137
	 * @return \Icewind\SMB\IFileInfo[]
138
	 * @throws StorageNotAvailableException
139
	 */
140
	protected function getFolderContents($path) {
141
		try {
142
			$path = $this->buildPath($path);
143
			$files = $this->share->dir($path);
144
			foreach ($files as $file) {
145
				$this->statCache[$path . '/' . $file->getName()] = $file;
146
			}
147
			return $files;
148
		} catch (ConnectException $e) {
1 ignored issue
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...
149
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
150
		}
151
	}
152
153
	/**
154
	 * @param \Icewind\SMB\IFileInfo $info
155
	 * @return array
156
	 */
157
	protected function formatInfo($info) {
158
		return array(
159
			'size' => $info->getSize(),
160
			'mtime' => $info->getMTime()
161
		);
162
	}
163
164
	/**
165
	 * @param string $path
166
	 * @return array
167
	 */
168
	public function stat($path) {
169
		return $this->formatInfo($this->getFileInfo($path));
170
	}
171
172
	/**
173
	 * @param string $path
174
	 * @return bool
175
	 */
176
	public function unlink($path) {
177
		try {
178
			if ($this->is_dir($path)) {
179
				return $this->rmdir($path);
180
			} else {
181
				$path = $this->buildPath($path);
182
				unset($this->statCache[$path]);
183
				$this->share->del($path);
184
				return true;
185
			}
186
		} catch (NotFoundException $e) {
1 ignored issue
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...
187
			return false;
188
		} catch (ForbiddenException $e) {
1 ignored issue
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...
189
			return false;
190
		} catch (ConnectException $e) {
1 ignored issue
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...
191
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
192
		}
193
	}
194
195
	/**
196
	 * check if a file or folder has been updated since $time
197
	 *
198
	 * @param string $path
199
	 * @param int $time
200
	 * @return bool
201
	 */
202
	public function hasUpdated($path, $time) {
203
		if (!$path and $this->root == '/') {
204
			// mtime doesn't work for shares, but giving the nature of the backend,
205
			// doing a full update is still just fast enough
206
			return true;
207
		} else {
208
			$actualTime = $this->filemtime($path);
209
			return $actualTime > $time;
210
		}
211
	}
212
213
	/**
214
	 * @param string $path
215
	 * @param string $mode
216
	 * @return resource
217
	 */
218
	public function fopen($path, $mode) {
219
		$fullPath = $this->buildPath($path);
220
		try {
221
			switch ($mode) {
222
				case 'r':
223
				case 'rb':
224
					if (!$this->file_exists($path)) {
225
						return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by OCA\Files_External\Lib\Storage\SMB::fopen of type resource.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
226
					}
227
					return $this->share->read($fullPath);
228
				case 'w':
229
				case 'wb':
230
					$source = $this->share->write($fullPath);
231
					return CallBackWrapper::wrap($source, null, null, function () use ($fullPath) {
232
						unset($this->statCache[$fullPath]);
233
					});
234
				case 'a':
235
				case 'ab':
236
				case 'r+':
237
				case 'w+':
238
				case 'wb+':
239
				case 'a+':
240
				case 'x':
241
				case 'x+':
242
				case 'c':
243
				case 'c+':
244
					//emulate these
245
					if (strrpos($path, '.') !== false) {
246
						$ext = substr($path, strrpos($path, '.'));
247
					} else {
248
						$ext = '';
249
					}
250 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...
251
						if (!$this->isUpdatable($path)) {
252
							return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by OCA\Files_External\Lib\Storage\SMB::fopen of type resource.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
253
						}
254
						$tmpFile = $this->getCachedFile($path);
255
					} else {
256
						if (!$this->isCreatable(dirname($path))) {
257
							return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by OCA\Files_External\Lib\Storage\SMB::fopen of type resource.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
258
						}
259
						$tmpFile = \OCP\Files::tmpFile($ext);
260
					}
261
					$source = fopen($tmpFile, $mode);
262
					$share = $this->share;
263
					return CallbackWrapper::wrap($source, null, null, function () use ($tmpFile, $fullPath, $share) {
264
						unset($this->statCache[$fullPath]);
265
						$share->put($tmpFile, $fullPath);
266
						unlink($tmpFile);
267
					});
268
			}
269
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by OCA\Files_External\Lib\Storage\SMB::fopen of type resource.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
270
		} catch (NotFoundException $e) {
1 ignored issue
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...
271
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by OCA\Files_External\Lib\Storage\SMB::fopen of type resource.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
272
		} catch (ForbiddenException $e) {
1 ignored issue
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...
273
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by OCA\Files_External\Lib\Storage\SMB::fopen of type resource.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
274
		} catch (ConnectException $e) {
1 ignored issue
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...
275
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
276
		}
277
	}
278
279
	public function rmdir($path) {
280
		try {
281
			$this->statCache = array();
282
			$content = $this->share->dir($this->buildPath($path));
283
			foreach ($content as $file) {
284
				if ($file->isDirectory()) {
285
					$this->rmdir($path . '/' . $file->getName());
286
				} else {
287
					$this->share->del($file->getPath());
288
				}
289
			}
290
			$this->share->rmdir($this->buildPath($path));
291
			return true;
292
		} catch (NotFoundException $e) {
1 ignored issue
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) {
1 ignored issue
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) {
1 ignored issue
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 View Code Duplication
	public function touch($path, $time = null) {
302
		try {
303
			if (!$this->file_exists($path)) {
304
				$fh = $this->share->write($this->buildPath($path));
305
				fclose($fh);
306
				return true;
307
			}
308
			return false;
309
		} catch (ConnectException $e) {
1 ignored issue
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...
310
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
311
		}
312
	}
313
314
	public function opendir($path) {
315
		try {
316
			$files = $this->getFolderContents($path);
317
		} catch (NotFoundException $e) {
1 ignored issue
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...
318
			return false;
319
		} catch (ForbiddenException $e) {
1 ignored issue
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...
320
			return false;
321
		}
322
		$names = array_map(function ($info) {
323
			/** @var \Icewind\SMB\IFileInfo $info */
324
			return $info->getName();
325
		}, $files);
326
		return IteratorDirectory::wrap($names);
327
	}
328
329
	public function filetype($path) {
330
		try {
331
			return $this->getFileInfo($path)->isDirectory() ? 'dir' : 'file';
332
		} catch (NotFoundException $e) {
1 ignored issue
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...
333
			return false;
334
		} catch (ForbiddenException $e) {
1 ignored issue
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...
335
			return false;
336
		}
337
	}
338
339 View Code Duplication
	public function mkdir($path) {
340
		$path = $this->buildPath($path);
341
		try {
342
			$this->share->mkdir($path);
343
			return true;
344
		} catch (ConnectException $e) {
1 ignored issue
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...
345
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
346
		} catch (Exception $e) {
1 ignored issue
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...
347
			return false;
348
		}
349
	}
350
351
	public function file_exists($path) {
352
		try {
353
			$this->getFileInfo($path);
354
			return true;
355
		} catch (NotFoundException $e) {
1 ignored issue
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...
356
			return false;
357
		} catch (ForbiddenException $e) {
1 ignored issue
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...
358
			return false;
359
		} catch (ConnectException $e) {
1 ignored issue
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...
360
			throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
361
		}
362
	}
363
364 View Code Duplication
	public function isReadable($path) {
365
		try {
366
			$info = $this->getFileInfo($path);
367
			return !$info->isHidden();
368
		} catch (NotFoundException $e) {
1 ignored issue
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...
369
			return false;
370
		} catch (ForbiddenException $e) {
1 ignored issue
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...
371
			return false;
372
		}
373
	}
374
375 View Code Duplication
	public function isUpdatable($path) {
376
		try {
377
			$info = $this->getFileInfo($path);
378
			return !$info->isHidden() && !$info->isReadOnly();
379
		} catch (NotFoundException $e) {
1 ignored issue
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...
380
			return false;
381
		} catch (ForbiddenException $e) {
1 ignored issue
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...
382
			return false;
383
		}
384
	}
385
386
	/**
387
	 * check if smbclient is installed
388
	 */
389
	public static function checkDependencies() {
390
		return (
391
			(bool)\OC_Helper::findBinaryPath('smbclient')
392
			|| Server::NativeAvailable()
393
		) ? true : ['smbclient'];
394
	}
395
396
	/**
397
	 * Test a storage for availability
398
	 *
399
	 * @return bool
400
	 */
401
	public function test() {
402
		try {
403
			return parent::test();
404
		} catch (Exception $e) {
1 ignored issue
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...
405
			return false;
406
		}
407
	}
408
409
	/**
410
	 * @param string $path
411
	 * @param callable $callback
412
	 */
413
	public function notify($path, callable $callback) {
414
		// we need to create a new share since we will be blocking the process fully
415
		if ($this->server instanceof NativeServer) { // notify is only supported by the smb client based backend at the moment
0 ignored issues
show
Bug introduced by
The class Icewind\SMB\NativeServer does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
416
			$server = new Server($this->server->getHost(), $this->server->getUser(), $this->server->getPassword());
417
		} else {
418
			$server = $this->server;
419
		}
420
		$share = $server->getShare($this->share->getName());
421
422
		$renameOld = null;
423
424
		$share->notify($path, function ($change, $path) use ($callback, &$renameOld) {
425
			unset($this->statCache[$this->buildPath($path)]);
426
			if ($change === self::NOTIFY_ADDED || $change === self::NOTIFY_REMOVED || $change === self::NOTIFY_MODIFIED) { // we can pass these directly
427
				return $callback($change, $path);
428
			} elseif ($change === self::NOTIFY_RENAME_OLD) {
429
				$renameOld = $path;
430
			} elseif ($change === self::NOTIFY_RENAME_NEW) {
431
				if (!is_null($renameOld)) {
432
					$oldPath = $renameOld;
433
					$renameOld = null;
434
					return $callback(self::NOTIFY_RENAME, $oldPath, $path);
435
				}
436
			}
437
		});
438
	}
439
}
440