Completed
Pull Request — master (#79)
by Raffael
18:33 queued 03:32
created

RawConnection   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 91.25%

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 2
dl 0
loc 177
ccs 73
cts 80
cp 0.9125
rs 10
c 0
b 0
f 0

17 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A isValid() 0 8 2
A write() 0 4 1
A readLine() 0 3 1
A getInputStream() 0 3 1
A getOutputStream() 0 3 1
A getAuthStream() 0 3 1
A connect() 0 27 3
A readAll() 0 7 2
A writeAuthentication() 0 8 2
A readError() 0 3 1
A getErrorStream() 0 3 1
A getFileInputStream() 0 3 1
A getFileOutputStream() 0 3 1
A close() 0 9 3
A reconnect() 0 4 1
A __destruct() 0 3 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\Wrapped;
9
10
use Icewind\SMB\Exception\ConnectException;
11
use Icewind\SMB\Exception\ConnectionException;
12
13
class RawConnection {
14
	/**
15
	 * @var string
16
	 */
17
	private $command;
18
19
	/**
20
	 * @var string[]
21
	 */
22
	private $env;
23
24
	/**
25
	 * @var resource[] $pipes
26
	 *
27
	 * $pipes[0] holds STDIN for smbclient
28
	 * $pipes[1] holds STDOUT for smbclient
29
	 * $pipes[3] holds the authfile for smbclient
30
	 * $pipes[4] holds the stream for writing files
31
	 * $pipes[5] holds the stream for reading files
32
	 */
33
	private $pipes;
34
35
	/**
36
	 * @var resource $process
37
	 */
38
	private $process;
39
40
	/**
41
	 * @var resource|null $authStream
42
	 */
43
	private $authStream = null;
44
45
	private $connected = false;
46
47 1040
	public function __construct($command, array $env = []) {
48 1040
		$this->command = $command;
49 1040
		$this->env = $env;
50 1040
	}
51
52
	/**
53
	 * @throws ConnectException
54
	 */
55 1040
	public function connect() {
56 1040
		if (is_null($this->getAuthStream())) {
57
			throw new ConnectException('Authentication not set before connecting');
58
		}
59
60
		$descriptorSpec = [
61 1040
			0 => ['pipe', 'r'], // child reads from stdin
62 260
			1 => ['pipe', 'w'], // child writes to stdout
63 260
			2 => ['pipe', 'w'], // child writes to stderr
64 1040
			3 => $this->getAuthStream(), // child reads from fd#3
65 260
			4 => ['pipe', 'r'], // child reads from fd#4
66 260
			5 => ['pipe', 'w']  // child writes to fd#5
67 260
		];
68
69 1040
		setlocale(LC_ALL, Server::LOCALE);
70 1040
		$env = array_merge($this->env, [
71 1040
			'CLI_FORCE_INTERACTIVE' => 'y', // Needed or the prompt isn't displayed!!
72 1040
			'LC_ALL'                => Server::LOCALE,
73 1040
			'LANG'                  => Server::LOCALE,
74 780
			'COLUMNS'               => 8192 // prevent smbclient from line-wrapping it's output
75 260
		]);
76 1040
		$this->process = proc_open($this->command, $descriptorSpec, $this->pipes, '/', $env);
77 1040
		if (!$this->isValid()) {
78
			throw new ConnectionException();
79
		}
80 1040
		$this->connected = true;
81 1040
	}
82
83
	/**
84
	 * check if the connection is still active
85
	 *
86
	 * @return bool
87
	 */
88 1040
	public function isValid() {
89 1040
		if (is_resource($this->process)) {
90 1040
			$status = proc_get_status($this->process);
91 1040
			return $status['running'];
92
		} else {
93
			return false;
94
		}
95
	}
96
97
	/**
98
	 * send input to the process
99
	 *
100
	 * @param string $input
101
	 */
102 1024
	public function write($input) {
103 1024
		fwrite($this->getInputStream(), $input);
104 1024
		fflush($this->getInputStream());
105 1024
	}
106
107
	/**
108
	 * read a line of output
109
	 *
110
	 * @return string|false
111
	 */
112 1040
	public function readLine() {
113 1040
		return stream_get_line($this->getOutputStream(), 4086, "\n");
114
	}
115
116
	/**
117
	 * read a line of output
118
	 *
119
	 * @return string
120
	 */
121
	public function readError() {
122
		return trim(stream_get_line($this->getErrorStream(), 4086));
123
	}
124
125
	/**
126
	 * get all output until the process closes
127
	 *
128
	 * @return array
129
	 */
130 20
	public function readAll() {
131 20
		$output = [];
132 20
		while ($line = $this->readLine()) {
133 20
			$output[] = $line;
134 5
		}
135 20
		return $output;
136
	}
137
138 1024
	public function getInputStream() {
139 1024
		return $this->pipes[0];
140
	}
141
142 1040
	public function getOutputStream() {
143 1040
		return $this->pipes[1];
144
	}
145
146
	public function getErrorStream() {
147
		return $this->pipes[2];
148
	}
149
150 1040
	public function getAuthStream() {
151 1040
		return $this->authStream;
152
	}
153
154 64
	public function getFileInputStream() {
155 64
		return $this->pipes[4];
156
	}
157
158 64
	public function getFileOutputStream() {
159 64
		return $this->pipes[5];
160
	}
161
162 1040
	public function writeAuthentication($user, $password) {
163 1040
		$auth = ($password === false)
164 260
			? "username=$user"
165 1040
			: "username=$user\npassword=$password\n";
166
167 1040
		$this->authStream = fopen('php://temp', 'w+');
168 1040
		fwrite($this->getAuthStream(), $auth);
169 1040
	}
170
171 1040
	public function close($terminate = true) {
172 1040
		if (!is_resource($this->process)) {
173 84
			return;
174
		}
175 1040
		if ($terminate) {
176
			proc_terminate($this->process);
177 1040
		}
178 1040
		proc_close($this->process);
179 1040
	}
180 1040
181 1040
	public function reconnect() {
182 1040
		$this->close();
183
		$this->connect();
184 1032
	}
185 256
186 260
	public function __destruct() {
187 260
		$this->close();
188 1040
	}
189
}
190