Completed
Push — master ( c1afd7...fa4918 )
by Robin
03:41
created

RawConnection::writeAuthentication()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0987

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 7
cts 9
cp 0.7778
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 4
nop 2
crap 3.0987
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 774
	public function __construct($command, $env = array()) {
37 774
		$this->command = $command;
38 774
		$this->env = $env;
39 774
		$this->connect();
40 774
	}
41
42 774
	private function connect() {
43
		$descriptorSpec = array(
44 774
			0 => array('pipe', 'r'), // child reads from stdin
45 774
			1 => array('pipe', 'w'), // child writes to stdout
46 774
			2 => array('pipe', 'w'), // child writes to stderr
47 774
			3 => array('pipe', 'r'), // child reads from fd#3
48 774
			4 => array('pipe', 'r'), // child reads from fd#4
49 774
			5 => array('pipe', 'w')  // child writes to fd#5
50 774
		);
51 774
		setlocale(LC_ALL, Server::LOCALE);
52 774
		$env = array_merge($this->env, array(
53 774
			'CLI_FORCE_INTERACTIVE' => 'y', // Needed or the prompt isn't displayed!!
54 774
			'LC_ALL' => Server::LOCALE,
55 774
			'LANG' => Server::LOCALE,
56
			'COLUMNS' => 8192 // prevent smbclient from line-wrapping it's output
57 774
		));
58 774
		$this->process = proc_open($this->command, $descriptorSpec, $this->pipes, '/', $env);
59 774
		if (!$this->isValid()) {
60
			throw new ConnectionException();
61
		}
62 774
	}
63
64
	/**
65
	 * check if the connection is still active
66
	 *
67
	 * @return bool
68
	 */
69 774
	public function isValid() {
70 774
		if (is_resource($this->process)) {
71 774
			$status = proc_get_status($this->process);
72 774
			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 762
	public function write($input) {
84 762
		fwrite($this->getInputStream(), $input);
85 762
		fflush($this->getInputStream());
86 762
	}
87
88
	/**
89
	 * read a line of output
90
	 *
91
	 * @return string
92
	 */
93 771
	public function readLine() {
94 771
		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 15
	public function readAll() {
112 15
		$output = array();
113 15
		while ($line = $this->readLine()) {
114 15
			$output[] = $line;
115 15
		}
116 15
		return $output;
117
	}
118
119 762
	public function getInputStream() {
120 762
		return $this->pipes[0];
121
	}
122
123 771
	public function getOutputStream() {
124 771
		return $this->pipes[1];
125
	}
126
127
	public function getErrorStream() {
128
		return $this->pipes[2];
129
	}
130
131 774
	public function getAuthStream() {
132 774
		return $this->pipes[3];
133
	}
134
135 48
	public function getFileInputStream() {
136 48
		return $this->pipes[4];
137
	}
138
139 48
	public function getFileOutputStream() {
140 48
		return $this->pipes[5];
141
	}
142
143 774
	public function writeAuthentication($user, $password) {
144 774
		$auth = ($password === false)
145 774
			? "username=$user"
146 774
			: "username=$user\npassword=$password";
147
148 774
		if (fwrite($this->getAuthStream(), $auth) === false) {
149
			fclose($this->getAuthStream());
150
			return false;
151
		}
152 774
		fclose($this->getAuthStream());
153 774
		return true;
154
	}
155
156 774
	public function close($terminate = true) {
157 774
		if (!is_resource($this->process)) {
158 60
			return;
159
		}
160 774
		if ($terminate) {
161
			// if for case that posix_ functions are not available
162 774
			if (function_exists('posix_kill')) {
163 774
				$status = proc_get_status($this->process);
164 774
				$ppid = $status['pid'];
165 774
				$pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`);
166 774
				foreach($pids as $pid) {
167 774
					if(is_numeric($pid)) {
168
						//9 is the SIGKILL signal
169 762
						posix_kill($pid, 9);
170 762
					}
171 774
				}
172 774
			}
173 774
			proc_terminate($this->process);
174 774
		}
175 774
		proc_close($this->process);
176 774
	}
177
178 3
	public function reconnect() {
179 3
		$this->close();
180 3
		$this->connect();
181 3
	}
182
183 774
	public function __destruct() {
184 774
		$this->close();
185 774
	}
186
}
187