Passed
Push — master ( c25309...927e33 )
by Robin
04:02 queued 29s
created

NativeFileInfo::isReadOnly()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 6
ccs 4
cts 5
cp 0.8
crap 2.032
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright (c) 2014 Robin Appelman <[email protected]>
4
 * This file is licensed under the Licensed under the MIT license:
5
 * http://opensource.org/licenses/MIT
6
 */
7
8
namespace Icewind\SMB\Native;
9
10
use Icewind\SMB\ACL;
11
use Icewind\SMB\IFileInfo;
12
13
class NativeFileInfo implements IFileInfo {
14
	/**
15
	 * @var string
16
	 */
17
	protected $path;
18
19
	/**
20
	 * @var string
21
	 */
22
	protected $name;
23
24
	/**
25
	 * @var NativeShare
26
	 */
27
	protected $share;
28
29
	/**
30
	 * @var array|null
31
	 */
32
	protected $attributeCache = null;
33
34
	/**
35
	 * @param NativeShare $share
36
	 * @param string $path
37
	 * @param string $name
38
	 */
39 210
	public function __construct($share, $path, $name) {
40 210
		$this->share = $share;
41 210
		$this->path = $path;
42 210
		$this->name = $name;
43 210
	}
44
45
	/**
46
	 * @return string
47
	 */
48 186
	public function getPath() {
49 186
		return $this->path;
50
	}
51
52
	/**
53
	 * @return string
54
	 */
55 98
	public function getName() {
56 98
		return $this->name;
57
	}
58
59
	/**
60
	 * @return array
61
	 */
62 210
	protected function stat() {
63 210
		if (is_null($this->attributeCache)) {
64 210
			$rawAttributes = explode(',', $this->share->getAttribute($this->path, 'system.dos_attr.*'));
65 190
			$this->attributeCache = [];
66 190
			foreach ($rawAttributes as $rawAttribute) {
67 190
				[$name, $value] = explode(':', $rawAttribute);
68 190
				$name = strtolower($name);
69 190
				if ($name == 'mode') {
70 190
					$this->attributeCache[$name] = (int)hexdec(substr($value, 2));
71
				} else {
72 190
					$this->attributeCache[$name] = (int)$value;
73
				}
74
			}
75
		}
76 190
		return $this->attributeCache;
77
	}
78
79
	/**
80
	 * @return int
81
	 */
82 80
	public function getSize() {
83 80
		$stat = $this->stat();
84 60
		return $stat['size'];
85
	}
86
87
	/**
88
	 * @return int
89
	 */
90 2
	public function getMTime() {
91 2
		$stat = $this->stat();
92 2
		return $stat['change_time'];
93
	}
94
95
	/**
96
	 * On "mode":
97
	 *
98
	 * different smbclient versions seem to return different mode values for 'system.dos_attr.mode'
99
	 *
100
	 * older versions return the dos permissions mask as defined in `IFileInfo::MODE_*` while
101
	 * newer versions return the equivalent unix permission mask.
102
	 *
103
	 * Since the unix mask doesn't contain the proper hidden/archive/system flags we have to assume them
104
	 * as false (except for `hidden` where we use the unix dotfile convention)
105
	 */
106
107
	/**
108
	 * @return int
109
	 */
110 186
	protected function getMode() {
111 186
		return $this->stat()['mode'];
112
	}
113
114
	/**
115
	 * @return bool
116
	 */
117 186
	public function isDirectory() {
118 186
		$mode = $this->getMode();
119 186
		if ($mode > 0x80) {
120
			return (bool)($mode & 0x4000); // 0x80: unix directory flag
121
		} else {
122 186
			return (bool)($mode & IFileInfo::MODE_DIRECTORY);
123
		}
124
	}
125
126
	/**
127
	 * @return bool
128
	 */
129 2
	public function isReadOnly() {
130 2
		$mode = $this->getMode();
131 2
		if ($mode > 0x80) {
132
			return !(bool)($mode & 0x80); // 0x80: owner write permissions
133
		} else {
134 2
			return (bool)($mode & IFileInfo::MODE_READONLY);
135
		}
136
	}
137
138
	/**
139
	 * @return bool
140
	 */
141 12
	public function isHidden() {
142 12
		$mode = $this->getMode();
143 12
		if ($mode > 0x80) {
144
			return $this->name[0] === '.';
145
		} else {
146 12
			return (bool)($mode & IFileInfo::MODE_HIDDEN);
147
		}
148
	}
149
150
	/**
151
	 * @return bool
152
	 */
153
	public function isSystem() {
154
		$mode = $this->getMode();
155
		if ($mode > 0x80) {
156
			return false;
157
		} else {
158
			return (bool)($mode & IFileInfo::MODE_SYSTEM);
159
		}
160
	}
161
162
	/**
163
	 * @return bool
164
	 */
165
	public function isArchived() {
166
		$mode = $this->getMode();
167
		if ($mode > 0x80) {
168
			return false;
169
		} else {
170
			return (bool)($mode & IFileInfo::MODE_ARCHIVE);
171
		}
172
	}
173
174
	/**
175
	 * @return ACL[]
176
	 */
177
	public function getAcls(): array {
178
		$acls = [];
179
		$attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+');
180
181
		foreach (explode(',', $attribute) as $acl) {
182
			[$user, $permissions] = explode(':', $acl, 2);
183
			[$type, $flags, $mask] = explode('/', $permissions);
184
			$mask = hexdec($mask);
185
186
			$acls[$user] = new ACL($type, $flags, $mask);
0 ignored issues
show
Bug introduced by
$flags of type string is incompatible with the type integer expected by parameter $flags of Icewind\SMB\ACL::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

186
			$acls[$user] = new ACL($type, /** @scrutinizer ignore-type */ $flags, $mask);
Loading history...
Bug introduced by
It seems like $mask can also be of type double; however, parameter $mask of Icewind\SMB\ACL::__construct() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

186
			$acls[$user] = new ACL($type, $flags, /** @scrutinizer ignore-type */ $mask);
Loading history...
Bug introduced by
$type of type string is incompatible with the type integer expected by parameter $type of Icewind\SMB\ACL::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

186
			$acls[$user] = new ACL(/** @scrutinizer ignore-type */ $type, $flags, $mask);
Loading history...
187
		}
188
189
		return $acls;
190
	}
191
}
192