Completed
Push — master ( 036dbf...97ea24 )
by Robin
08:23
created

RawConnection::getErrorStream()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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