Passed
Push — master ( 8481d6...507b18 )
by Robin
03:14
created

NativeFileInfo::getSize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
ccs 3
cts 3
cp 1
crap 1
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 184
	public function getPath() {
49 184
		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
				list($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 82
	public function getSize() {
83 82
		$stat = $this->stat();
84 62
		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 184
	protected function getMode() {
111 184
		$mode = $this->stat()['mode'];
112
113
		// Let us ignore the ATTR_NOT_CONTENT_INDEXED for now
114 184
		$mode &= ~0x00002000;
115
		
116 184
		return $this->stat()['mode'];
117
	}
118
119
	/**
120
	 * @return bool
121
	 */
122 184
	public function isDirectory() {
123 184
		$mode = $this->getMode();
124 184
		if ($mode > 0x1000) {
125
			return (bool)($mode & 0x4000); // 0x4000: unix directory flag
126
		} else {
127 184
			return (bool)($mode & IFileInfo::MODE_DIRECTORY);
128
		}
129
	}
130
131
	/**
132
	 * @return bool
133
	 */
134 2
	public function isReadOnly() {
135 2
		$mode = $this->getMode();
136 2
		if ($mode > 0x1000) {
137
			return !(bool)($mode & 0x80); // 0x80: owner write permissions
138
		} else {
139 2
			return (bool)($mode & IFileInfo::MODE_READONLY);
140
		}
141
	}
142
143
	/**
144
	 * @return bool
145
	 */
146 12
	public function isHidden() {
147 12
		$mode = $this->getMode();
148 12
		if ($mode > 0x1000) {
149
			return strlen($this->name) > 0 && $this->name[0] === '.';
150
		} else {
151 12
			return (bool)($mode & IFileInfo::MODE_HIDDEN);
152
		}
153
	}
154
155
	/**
156
	 * @return bool
157
	 */
158
	public function isSystem() {
159
		$mode = $this->getMode();
160
		if ($mode > 0x1000) {
161
			return false;
162
		} else {
163
			return (bool)($mode & IFileInfo::MODE_SYSTEM);
164
		}
165
	}
166
167
	/**
168
	 * @return bool
169
	 */
170
	public function isArchived() {
171
		$mode = $this->getMode();
172
		if ($mode > 0x1000) {
173
			return false;
174
		} else {
175
			return (bool)($mode & IFileInfo::MODE_ARCHIVE);
176
		}
177
	}
178
179
	/**
180
	 * @return ACL[]
181
	 */
182
	public function getAcls(): array {
183
		$acls = [];
184
		$attribute = $this->share->getAttribute($this->path, 'system.nt_sec_desc.acl.*+');
185
186
		foreach (explode(',', $attribute) as $acl) {
187
			list($user, $permissions) = explode(':', $acl, 2);
188
			list($type, $flags, $mask) = explode('/', $permissions);
189
			$mask = hexdec($mask);
190
191
			$acls[$user] = new ACL($type, $flags, $mask);
0 ignored issues
show
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

191
			$acls[$user] = new ACL(/** @scrutinizer ignore-type */ $type, $flags, $mask);
Loading history...
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

191
			$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

191
			$acls[$user] = new ACL($type, $flags, /** @scrutinizer ignore-type */ $mask);
Loading history...
192
		}
193
194
		return $acls;
195
	}
196
}
197