Completed
Push — master ( 1bf43b...c1afd7 )
by Robin
01:56
created

Connection::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 3
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\AuthenticationException;
11
use Icewind\SMB\Exception\ConnectException;
12
use Icewind\SMB\Exception\ConnectionException;
13
use Icewind\SMB\Exception\InvalidHostException;
14
use Icewind\SMB\Exception\NoLoginServerException;
15
16
class Connection extends RawConnection {
17
	const DELIMITER = 'smb:';
18
	const DELIMITER_LENGTH = 4;
19
20
	/** @var Parser */
21
	private $parser;
22
23 508
	public function __construct($command, Parser $parser, $env = array()) {
24 508
		parent::__construct($command, $env);
25 508
		$this->parser = $parser;
26 508
	}
27
28
	/**
29
	 * send input to smbclient
30
	 *
31
	 * @param string $input
32
	 */
33 508
	public function write($input) {
34 508
		parent::write($input . PHP_EOL);
35 508
	}
36
37
	/**
38
	 * get all unprocessed output from smbclient until the next prompt
39
	 *
40
	 * @param callable $callback (optional) callback to call for every line read
41
	 * @return string[]
42
	 * @throws AuthenticationException
43
	 * @throws ConnectException
44
	 * @throws ConnectionException
45
	 * @throws InvalidHostException
46
	 * @throws NoLoginServerException
47
	 */
48 506
	public function read(callable $callback = null) {
49 506
		if (!$this->isValid()) {
50
			throw new ConnectionException('Connection not valid');
51
		}
52 506
		$promptLine = $this->readLine(); //first line is prompt
53 506
		$this->parser->checkConnectionError($promptLine);
54
55 506
		$output = array();
56 506
		$line = $this->readLine();
57 506
		if ($line === false) {
58
			$this->unknownError($promptLine);
59
		}
60 506
		while (!$this->isPrompt($line)) { //next prompt functions as delimiter
61 502
			if (is_callable($callback)) {
62 2
				$result = $callback($line);
63 2
				if ($result === false) { // allow the callback to close the connection for infinite running commands
64 2
					$this->close(true);
65 2
					break;
66
				}
67
			} else {
68 500
				$output[] .= $line;
69
			}
70 500
			$line = $this->readLine();
71 250
		}
72 506
		return $output;
73
	}
74
75
	/**
76
	 * Check
77
	 *
78
	 * @param $line
79
	 * @return bool
80
	 */
81 506
	private function isPrompt($line) {
82 506
		return mb_substr($line, 0, self::DELIMITER_LENGTH) === self::DELIMITER || $line === false;
83
	}
84
85
	/**
86
	 * @param string $promptLine (optional) prompt line that might contain some info about the error
87
	 * @throws ConnectException
88
	 */
89
	private function unknownError($promptLine = '') {
90
		if ($promptLine) { //maybe we have some error we missed on the previous line
91
			throw new ConnectException('Unknown error (' . $promptLine . ')');
92
		} else {
93
			$error = $this->readError(); // maybe something on stderr
94
			if ($error) {
95
				throw new ConnectException('Unknown error (' . $error . ')');
96
			} else {
97
				throw new ConnectException('Unknown error');
98
			}
99
		}
100
	}
101
102 508
	public function close($terminate = true) {
103 508
		if (is_resource($this->getInputStream())) {
104 508
			$this->write('close' . PHP_EOL);
105 254
		}
106 508
		parent::close($terminate);
107 508
	}
108
}
109