Completed
Pull Request — master (#31)
by Blizzz
13:09 queued 04:36
created

Node::getFileInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 2 Features 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 2
b 2
f 0
1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Bart Visscher <[email protected]>
5
 * @author Björn Schießle <[email protected]>
6
 * @author Jakob Sack <[email protected]>
7
 * @author Jörn Friedrich Dreyer <[email protected]>
8
 * @author Klaas Freitag <[email protected]>
9
 * @author Markus Goetz <[email protected]>
10
 * @author Morris Jobke <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Roeland Jago Douma <[email protected]>
13
 * @author Thomas Müller <[email protected]>
14
 * @author Vincent Petry <[email protected]>
15
 *
16
 * @copyright Copyright (c) 2016, ownCloud, Inc.
17
 * @license AGPL-3.0
18
 *
19
 * This code is free software: you can redistribute it and/or modify
20
 * it under the terms of the GNU Affero General Public License, version 3,
21
 * as published by the Free Software Foundation.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
 * GNU Affero General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU Affero General Public License, version 3,
29
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
30
 *
31
 */
32
33
namespace OCA\DAV\Connector\Sabre;
34
35
use OC\Files\Mount\MoveableMount;
36
use OCA\DAV\Connector\Sabre\Exception\InvalidPath;
37
use OCP\Share\Exceptions\ShareNotFound;
38
use OCP\Share\IManager;
39
40
41
abstract class Node implements \Sabre\DAV\INode {
42
43
	/**
44
	 * @var \OC\Files\View
45
	 */
46
	protected $fileView;
47
48
	/**
49
	 * The path to the current node
50
	 *
51
	 * @var string
52
	 */
53
	protected $path;
54
55
	/**
56
	 * node properties cache
57
	 *
58
	 * @var array
59
	 */
60
	protected $property_cache = null;
61
62
	/**
63
	 * @var \OCP\Files\FileInfo
64
	 */
65
	protected $info;
66
67
	/**
68
	 * @var IManager
69
	 */
70
	protected $shareManager;
71
72
	/**
73
	 * Sets up the node, expects a full path name
74
	 *
75
	 * @param \OC\Files\View $view
76
	 * @param \OCP\Files\FileInfo $info
77
	 * @param IManager $shareManager
78
	 */
79
	public function __construct($view, $info, IManager $shareManager = null) {
80
		$this->fileView = $view;
81
		$this->path = $this->fileView->getRelativePath($info->getPath());
82
		$this->info = $info;
83
		if ($shareManager) {
84
			$this->shareManager = $shareManager;
85
		} else {
86
			$this->shareManager = \OC::$server->getShareManager();
87
		}
88
	}
89
90
	protected function refreshInfo() {
91
		$this->info = $this->fileView->getFileInfo($this->path);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->fileView->getFileInfo($this->path) can also be of type false. However, the property $info is declared as type object<OCP\Files\FileInfo>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
92
	}
93
94
	/**
95
	 *  Returns the name of the node
96
	 *
97
	 * @return string
98
	 */
99
	public function getName() {
100
		return $this->info->getName();
101
	}
102
103
	/**
104
	 * Returns the full path
105
	 *
106
	 * @return string
107
	 */
108
	public function getPath() {
109
		return $this->path;
110
	}
111
112
	/**
113
	 * Renames the node
114
	 *
115
	 * @param string $name The new name
116
	 * @throws \Sabre\DAV\Exception\BadRequest
117
	 * @throws \Sabre\DAV\Exception\Forbidden
118
	 */
119
	public function setName($name) {
120
121
		// rename is only allowed if the update privilege is granted
122
		if (!$this->info->isUpdateable()) {
123
			throw new \Sabre\DAV\Exception\Forbidden();
124
		}
125
126
		list($parentPath,) = \Sabre\HTTP\URLUtil::splitPath($this->path);
127
		list(, $newName) = \Sabre\HTTP\URLUtil::splitPath($name);
128
129
		// verify path of the target
130
		$this->verifyPath();
131
132
		$newPath = $parentPath . '/' . $newName;
133
134
		$this->fileView->rename($this->path, $newPath);
135
136
		$this->path = $newPath;
137
138
		$this->refreshInfo();
139
	}
140
141
	public function setPropertyCache($property_cache) {
142
		$this->property_cache = $property_cache;
143
	}
144
145
	/**
146
	 * Returns the last modification time, as a unix timestamp
147
	 *
148
	 * @return int timestamp as integer
149
	 */
150
	public function getLastModified() {
151
		$timestamp = $this->info->getMtime();
152
		if (!empty($timestamp)) {
153
			return (int)$timestamp;
154
		}
155
		return $timestamp;
156
	}
157
158
	/**
159
	 *  sets the last modification time of the file (mtime) to the value given
160
	 *  in the second parameter or to now if the second param is empty.
161
	 *  Even if the modification time is set to a custom value the access time is set to now.
162
	 */
163
	public function touch($mtime) {
164
		$this->fileView->touch($this->path, $mtime);
165
		$this->refreshInfo();
166
	}
167
168
	/**
169
	 * Returns the ETag for a file
170
	 *
171
	 * An ETag is a unique identifier representing the current version of the
172
	 * file. If the file changes, the ETag MUST change.  The ETag is an
173
	 * arbitrary string, but MUST be surrounded by double-quotes.
174
	 *
175
	 * Return null if the ETag can not effectively be determined
176
	 *
177
	 * @return string
178
	 */
179
	public function getETag() {
180
		return '"' . $this->info->getEtag() . '"';
181
	}
182
183
	/**
184
	 * Sets the ETag
185
	 *
186
	 * @param string $etag
187
	 *
188
	 * @return int file id of updated file or -1 on failure
189
	 */
190
	public function setETag($etag) {
191
		return $this->fileView->putFileInfo($this->path, array('etag' => $etag));
192
	}
193
194
	/**
195
	 * Returns the size of the node, in bytes
196
	 *
197
	 * @return integer
198
	 */
199
	public function getSize() {
200
		return $this->info->getSize();
201
	}
202
203
	/**
204
	 * Returns the cache's file id
205
	 *
206
	 * @return int
207
	 */
208
	public function getId() {
209
		return $this->info->getId();
210
	}
211
212
	/**
213
	 * @return string|null
214
	 */
215
	public function getFileId() {
216
		if ($this->info->getId()) {
217
			$instanceId = \OC_Util::getInstanceId();
218
			$id = sprintf('%08d', $this->info->getId());
219
			return $id . $instanceId;
220
		}
221
222
		return null;
223
	}
224
225
	/**
226
	 * @return integer
227
	 */
228
	public function getInternalFileId() {
229
		return $this->info->getId();
230
	}
231
232
	/**
233
	 * @param string $user
234
	 * @return int
235
	 */
236
	public function getSharePermissions($user) {
237
238
		// check of we access a federated share
239
		if ($user !== null) {
240
			try {
241
				$share = $this->shareManager->getShareByToken($user);
242
				return $share->getPermissions();
243
			} catch (ShareNotFound $e) {
244
				// ignore
245
			}
246
		}
247
248
		$storage = $this->info->getStorage();
249
250
		$path = $this->info->getInternalPath();
251
252
		if ($storage->instanceOfStorage('\OC\Files\Storage\Shared')) {
253
			/** @var \OC\Files\Storage\Shared $storage */
254
			$permissions = (int)$storage->getShare()->getPermissions();
255
		} else {
256
			$permissions = $storage->getPermissions($path);
257
		}
258
259
		/*
260
		 * We can always share non moveable mount points with DELETE and UPDATE
261
		 * Eventually we need to do this properly
262
		 */
263
		$mountpoint = $this->info->getMountPoint();
264
		if (!($mountpoint instanceof MoveableMount)) {
265
			$mountpointpath = $mountpoint->getMountPoint();
266
			if (substr($mountpointpath, -1) === '/') {
267
				$mountpointpath = substr($mountpointpath, 0, -1);
268
			}
269
270
			if ($mountpointpath === $this->info->getPath()) {
271
				$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
272
			}
273
		}
274
275
		/*
276
		 * Files can't have create or delete permissions
277
		 */
278
		if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
279
			$permissions &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE);
280
		}
281
282
		return $permissions;
283
	}
284
285
	/**
286
	 * @return string
287
	 */
288
	public function getDavPermissions() {
289
		$p = '';
290
		if ($this->info->isShared()) {
291
			$p .= 'S';
292
		}
293
		if ($this->info->isShareable()) {
294
			$p .= 'R';
295
		}
296
		if ($this->info->isMounted()) {
297
			$p .= 'M';
298
		}
299
		if ($this->info->isDeletable()) {
300
			$p .= 'D';
301
		}
302
		if ($this->info->isUpdateable()) {
303
			$p .= 'NV'; // Renameable, Moveable
304
		}
305
		if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
306
			if ($this->info->isUpdateable()) {
307
				$p .= 'W';
308
			}
309
		} else {
310
			if ($this->info->isCreatable()) {
311
				$p .= 'CK';
312
			}
313
		}
314
		return $p;
315
	}
316
317
	public function getOwner() {
318
		return $this->info->getOwner();
319
	}
320
321
	protected function verifyPath() {
322
		try {
323
			$fileName = basename($this->info->getPath());
324
			$this->fileView->verifyPath($this->path, $fileName);
325
		} catch (\OCP\Files\InvalidPathException $ex) {
326
			throw new InvalidPath($ex->getMessage());
327
		}
328
	}
329
330
	/**
331
	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
332
	 */
333
	public function acquireLock($type) {
334
		$this->fileView->lockFile($this->path, $type);
335
	}
336
337
	/**
338
	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
339
	 */
340
	public function releaseLock($type) {
341
		$this->fileView->unlockFile($this->path, $type);
342
	}
343
344
	/**
345
	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
346
	 */
347
	public function changeLock($type) {
348
		$this->fileView->changeLock($this->path, $type);
349
	}
350
351
	public function getFileInfo() {
352
		return $this->info;
353
	}
354
}
355