Completed
Push — notifyhandler ( ebc1c0...c1afd7 )
by Robin
04:14
created

NativeShare::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
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;
9
10
use Icewind\SMB\Exception\InvalidPathException;
11
use Icewind\SMB\Exception\InvalidResourceException;
12
13
class NativeShare extends AbstractShare {
14
	/**
15
	 * @var Server $server
16
	 */
17
	private $server;
18
19
	/**
20
	 * @var string $name
21
	 */
22
	private $name;
23
24
	/**
25
	 * @var \Icewind\SMB\NativeState $state
26
	 */
27
	private $state;
28
29
	/**
30
	 * @param Server $server
31
	 * @param string $name
32
	 */
33 508
	public function __construct($server, $name) {
34 508
		parent::__construct();
35 508
		$this->server = $server;
36 508
		$this->name = $name;
37 508
		$this->state = new NativeState();
38 508
	}
39
40
	/**
41
	 * @throws \Icewind\SMB\Exception\ConnectionException
42
	 * @throws \Icewind\SMB\Exception\AuthenticationException
43
	 * @throws \Icewind\SMB\Exception\InvalidHostException
44
	 */
45 508
	protected function connect() {
46 508
		if ($this->state and $this->state instanceof NativeShare) {
47
			return;
48
		}
49
50 508
		$this->state->init($this->server->getWorkgroup(), $this->server->getUser(), $this->server->getPassword());
51 508
	}
52
53
	/**
54
	 * Get the name of the share
55
	 *
56
	 * @return string
57
	 */
58 2
	public function getName() {
59 2
		return $this->name;
60
	}
61
62 508
	private function buildUrl($path) {
63 508
		$this->connect();
64 508
		$this->verifyPath($path);
65 508
		$url = sprintf('smb://%s/%s', $this->server->getHost(), $this->name);
66 508
		if ($path) {
67 508
			$path = trim($path, '/');
68 508
			$url .= '/';
69 508
			$url .= implode('/', array_map('rawurlencode', explode('/', $path)));
70 508
		}
71 508
		return $url;
72
	}
73
74
	/**
75
	 * List the content of a remote folder
76
	 *
77
	 * @param string $path
78
	 * @return \Icewind\SMB\IFileInfo[]
79
	 *
80
	 * @throws \Icewind\SMB\Exception\NotFoundException
81
	 * @throws \Icewind\SMB\Exception\InvalidTypeException
82
	 */
83 508
	public function dir($path) {
84 508
		$files = array();
85
86 508
		$dh = $this->state->opendir($this->buildUrl($path));
87 508
		while ($file = $this->state->readdir($dh)) {
88 508
			$name = $file['name'];
89 508
			if ($name !== '.' and $name !== '..') {
90 202
				$files [] = new NativeFileInfo($this, $path . '/' . $name, $name);
91 202
			}
92 508
		}
93
94 508
		$this->state->closedir($dh);
95 508
		return $files;
96
	}
97
98
	/**
99
	 * @param string $path
100
	 * @return \Icewind\SMB\IFileInfo[]
101
	 */
102 66
	public function stat($path) {
103 66
		return new NativeFileInfo($this, $path, basename($path), $this->getStat($path));
104
	}
105
106 226
	public function getStat($path) {
107 226
		return $this->state->stat($this->buildUrl($path));
108
	}
109
110
	/**
111
	 * Create a folder on the share
112
	 *
113
	 * @param string $path
114
	 * @return bool
115
	 *
116
	 * @throws \Icewind\SMB\Exception\NotFoundException
117
	 * @throws \Icewind\SMB\Exception\AlreadyExistsException
118
	 */
119 508
	public function mkdir($path) {
120 508
		return $this->state->mkdir($this->buildUrl($path));
121
	}
122
123
	/**
124
	 * Remove a folder on the share
125
	 *
126
	 * @param string $path
127
	 * @return bool
128
	 *
129
	 * @throws \Icewind\SMB\Exception\NotFoundException
130
	 * @throws \Icewind\SMB\Exception\InvalidTypeException
131
	 */
132 508
	public function rmdir($path) {
133 508
		return $this->state->rmdir($this->buildUrl($path));
134
	}
135
136
	/**
137
	 * Delete a file on the share
138
	 *
139
	 * @param string $path
140
	 * @return bool
141
	 *
142
	 * @throws \Icewind\SMB\Exception\NotFoundException
143
	 * @throws \Icewind\SMB\Exception\InvalidTypeException
144
	 */
145 266
	public function del($path) {
146 266
		return $this->state->unlink($this->buildUrl($path));
147
	}
148
149
	/**
150
	 * Rename a remote file
151
	 *
152
	 * @param string $from
153
	 * @param string $to
154
	 * @return bool
155
	 *
156
	 * @throws \Icewind\SMB\Exception\NotFoundException
157
	 * @throws \Icewind\SMB\Exception\AlreadyExistsException
158
	 */
159 54
	public function rename($from, $to) {
160 54
		return $this->state->rename($this->buildUrl($from), $this->buildUrl($to));
161
	}
162
163
	/**
164
	 * Upload a local file
165
	 *
166
	 * @param string $source local file
167
	 * @param string $target remove file
168
	 * @return bool
169
	 *
170
	 * @throws \Icewind\SMB\Exception\NotFoundException
171
	 * @throws \Icewind\SMB\Exception\InvalidTypeException
172
	 */
173 226
	public function put($source, $target) {
174 226
		$sourceHandle = fopen($source, 'rb');
175 226
		$targetHandle = $this->state->create($this->buildUrl($target));
176
177 204
		while ($data = fread($sourceHandle, 4096)) {
178 204
			$this->state->write($targetHandle, $data);
179 204
		}
180 204
		$this->state->close($targetHandle);
181 204
		return true;
182
	}
183
184
	/**
185
	 * Download a remote file
186
	 *
187
	 * @param string $source remove file
188
	 * @param string $target local file
189
	 * @return bool
190
	 *
191
	 * @throws \Icewind\SMB\Exception\NotFoundException
192
	 * @throws \Icewind\SMB\Exception\InvalidTypeException
193
	 * @throws \Icewind\SMB\Exception\InvalidPathException
194
	 * @throws \Icewind\SMB\Exception\InvalidResourceException
195
	 */
196 88
	public function get($source, $target) {
197 88
		if (!$target) {
198 18
			throw new InvalidPathException('Invalid target path: Filename cannot be empty');
199
		}
200 70
		$targetHandle = @fopen($target, 'wb');
201 70
		if (!$targetHandle) {
202 2
			$error = error_get_last();
203 2
			if (is_array($error)) {
204 2
				$reason = $error['message'];
205 2
			} else {
206
				$reason = 'Unknown error';
207
			}
208 2
			throw new InvalidResourceException('Failed opening local file "' . $target . '" for writing: ' . $reason);
209
		}
210
211 68
		$sourceHandle = $this->state->open($this->buildUrl($source), 'r');
212 64
		if (!$sourceHandle) {
213
			fclose($targetHandle);
214
			throw new InvalidResourceException('Failed opening remote file "' . $source . '" for reading');
215
		}
216
217 64
		while ($data = $this->state->read($sourceHandle, 4096)) {
218 64
			fwrite($targetHandle, $data);
219 64
		}
220 64
		$this->state->close($sourceHandle);
221 64
		return true;
222
	}
223
224
	/**
225
	 * Open a readable stream top a remote file
226
	 *
227
	 * @param string $source
228
	 * @return resource a read only stream with the contents of the remote file
229
	 *
230
	 * @throws \Icewind\SMB\Exception\NotFoundException
231
	 * @throws \Icewind\SMB\Exception\InvalidTypeException
232
	 */
233 58
	public function read($source) {
234 58
		$url = $this->buildUrl($source);
235 40
		$handle = $this->state->open($url, 'r');
236 40
		return NativeStream::wrap($this->state, $handle, 'r', $url);
237
	}
238
239
	/**
240
	 * Open a readable stream top a remote file
241
	 *
242
	 * @param string $source
243
	 * @return resource a read only stream with the contents of the remote file
244
	 *
245
	 * @throws \Icewind\SMB\Exception\NotFoundException
246
	 * @throws \Icewind\SMB\Exception\InvalidTypeException
247
	 */
248 58
	public function write($source) {
249 58
		$url = $this->buildUrl($source);
250 40
		$handle = $this->state->create($url);
251 40
		return NativeStream::wrap($this->state, $handle, 'w', $url);
252
	}
253
254
	/**
255
	 * Get extended attributes for the path
256
	 *
257
	 * @param string $path
258
	 * @param string $attribute attribute to get the info
259
	 * @return string the attribute value
260
	 */
261 28
	public function getAttribute($path, $attribute) {
262 28
		return $this->state->getxattr($this->buildUrl($path), $attribute);
263
	}
264
265
	/**
266
	 * Get extended attributes for the path
267
	 *
268
	 * @param string $path
269
	 * @param string $attribute attribute to get the info
270
	 * @param mixed $value
271
	 * @return string the attribute value
272
	 */
273 16
	public function setAttribute($path, $attribute, $value) {
274
275 16
		if ($attribute === 'system.dos_attr.mode' and is_int($value)) {
276 16
			$value = '0x' . dechex($value);
277 16
		}
278
279 16
		return $this->state->setxattr($this->buildUrl($path), $attribute, $value);
280
	}
281
282
	/**
283
	 * @param string $path
284
	 * @param int $mode a combination of FileInfo::MODE_READONLY, FileInfo::MODE_ARCHIVE, FileInfo::MODE_SYSTEM and FileInfo::MODE_HIDDEN, FileInfo::NORMAL
285
	 * @return mixed
286
	 */
287 16
	public function setMode($path, $mode) {
288 16
		return $this->setAttribute($path, 'system.dos_attr.mode', $mode);
289
	}
290
291
	/**
292
	 * @param string $path
293
	 * @return INotifyHandler
294
	 */
295
	public function notify($path) {
296
		// php-smbclient does support notify (https://github.com/eduardok/libsmbclient-php/issues/29)
297
		// so we use the smbclient based backend for this
298
		$share = new Share($this->server, $this->getName());
299
		return $share->notify($path);
300
	}
301
302 508
	public function __destruct() {
303 508
		unset($this->state);
304 508
	}
305
}
306