Passed
Push — master ( 742be8...9fb175 )
by Robin
04:11
created

RawConnection::getInputStream()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
ccs 2
cts 2
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\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 514
	public function __construct($command, array $env = []) {
48 514
		$this->command = $command;
49 514
		$this->env = $env;
50 514
	}
51
52
	/**
53
	 * @throws ConnectException
54
	 */
55 514
	public function connect() {
56 514
		if (is_null($this->getAuthStream())) {
57
			throw new ConnectException('Authentication not set before connecting');
58
		}
59
60
		$descriptorSpec = [
61 514
			0 => ['pipe', 'r'], // child reads from stdin
62
			1 => ['pipe', 'w'], // child writes to stdout
63
			2 => ['pipe', 'w'], // child writes to stderr
64 514
			3 => $this->getAuthStream(), // child reads from fd#3
65
			4 => ['pipe', 'r'], // child reads from fd#4
66
			5 => ['pipe', 'w']  // child writes to fd#5
67
		];
68
69 514
		setlocale(LC_ALL, Server::LOCALE);
70 514
		$env = array_merge($this->env, [
71 514
			'CLI_FORCE_INTERACTIVE' => 'y', // Needed or the prompt isn't displayed!!
72 514
			'LC_ALL'                => Server::LOCALE,
73 514
			'LANG'                  => Server::LOCALE,
74 514
			'COLUMNS'               => 8192 // prevent smbclient from line-wrapping it's output
75
		]);
76 514
		$this->process = proc_open($this->command, $descriptorSpec, $this->pipes, '/', $env);
0 ignored issues
show
Documentation Bug introduced by
It seems like proc_open($this->command...this->pipes, '/', $env) can also be of type false. However, the property $process is declared as type resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
77 514
		if (!$this->isValid()) {
78
			throw new ConnectionException();
79
		}
80 514
		$this->connected = true;
81 514
	}
82
83
	/**
84
	 * check if the connection is still active
85
	 *
86
	 * @return bool
87
	 */
88 514
	public function isValid() {
89 514
		if (is_resource($this->process)) {
90 514
			$status = proc_get_status($this->process);
91 514
			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 508
	public function write($input) {
103 508
		fwrite($this->getInputStream(), $input);
104 508
		fflush($this->getInputStream());
105 508
	}
106
107
	/**
108
	 * read a line of output
109
	 *
110
	 * @return string|false
111
	 */
112 514
	public function readLine() {
113 514
		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 6
	public function readAll() {
131 6
		$output = [];
132 6
		while ($line = $this->readLine()) {
133 6
			$output[] = $line;
134
		}
135 6
		return $output;
136
	}
137
138 508
	public function getInputStream() {
139 508
		return $this->pipes[0];
140
	}
141
142 514
	public function getOutputStream() {
143 514
		return $this->pipes[1];
144
	}
145
146
	public function getErrorStream() {
147
		return $this->pipes[2];
148
	}
149
150 514
	public function getAuthStream() {
151 514
		return $this->authStream;
152
	}
153
154 32
	public function getFileInputStream() {
155 32
		return $this->pipes[4];
156
	}
157
158 32
	public function getFileOutputStream() {
159 32
		return $this->pipes[5];
160
	}
161
162 514
	public function writeAuthentication($user, $password) {
163 514
		$auth = ($password === false)
164
			? "username=$user"
165 514
			: "username=$user\npassword=$password\n";
166
167 514
		$this->authStream = fopen('php://temp', 'w+');
0 ignored issues
show
Documentation Bug introduced by
It seems like fopen('php://temp', 'w+') can also be of type false. However, the property $authStream is declared as type null|resource. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
168 514
		fwrite($this->getAuthStream(), $auth);
0 ignored issues
show
Bug introduced by
It seems like $this->getAuthStream() can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, 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

168
		fwrite(/** @scrutinizer ignore-type */ $this->getAuthStream(), $auth);
Loading history...
169 514
	}
170
171 514
	public function close($terminate = true) {
172 514
		if (!is_resource($this->process)) {
173 42
			return;
174
		}
175 514
		if ($terminate) {
176 514
			proc_terminate($this->process);
177
		}
178 514
		proc_close($this->process);
179 514
	}
180
181 2
	public function reconnect() {
182 2
		$this->close();
183 2
		$this->connect();
184 2
	}
185
186 514
	public function __destruct() {
187 514
		$this->close();
188 514
	}
189
}
190