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

Connection   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 74.42%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 15
c 1
b 1
f 0
lcom 1
cbo 4
dl 0
loc 93
ccs 32
cts 43
cp 0.7442
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A write() 0 3 1
B read() 0 26 6
A isPrompt() 0 3 2
A unknownError() 0 12 3
A close() 0 6 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\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