Issues (41)

src/protected/models/WebServer.php (2 issues)

Severity
1
<?php
2
3
/**
4
 * Represents a web server. It provides methods for testing that the server 
5
 * behaves as expected (e.g. requires authentication).
6
 *
7
 * @author Sam Stenvall <[email protected]>
8
 * @copyright Copyright &copy; Sam Stenvall 2014-
9
 * @license https://www.gnu.org/licenses/gpl.html The GNU General Public License v3.0
10
 */
11
class WebServer
12
{
13
	
14
	/**
15
	 * @var string the server hostname
16
	 */
17
	private $_hostname;
18
	
19
	/**
20
	 * @var int the server port
21
	 */
22
	private $_port;
23
	
24
	/**
25
	 * @var \Zend\Http\Client() the HTTP client used
26
	 */
27
	private $_httpClient;
28
	
29
	/**
30
	 * Class constructor. It instantiates the HTTP client.
31
	 * @param string $hostname the server hostname
32
	 * @param int $port the server port
33
	 */
34
	public function __construct($hostname, $port)
35
	{
36
		$this->_hostname = $hostname;
37
		$this->_port = $port;
38
		$this->_httpClient = new Zend\Http\Client();
39
	}
40
	
41
	/**
42
	 * @return boolean whether the web server requires authentication
43
	 */
44
	public function requiresAuthentication()
45
	{
46
		return $this->getResponseStatusCode($this->createBasicRequest()) === 401;
47
	}
48
	
49
	/**
50
	 * @return string the authentication realm of the server, or an empty string 
51
	 * if no authentication is requested
52
	 */
53
	public function getAuthenticationRealm()
54
	{
55
		$response = $this->silentDispatch($this->createBasicRequest());
56
57
		if ($response)
0 ignored issues
show
$response is of type Zend\Http\Response, thus it always evaluated to true.
Loading history...
58
			foreach ($response->getHeaders() as $header)
59
				if ($header instanceof Zend\Http\Header\WWWAuthenticate)
60
					return $this->parseRealm($header);
61
62
		return '';
63
	}
64
	
65
	/**
66
	 * Checks that the specified credentials are valid
67
	 * @param string $username the username
68
	 * @param string $password the password
69
	 * @return boolean whether authentication succeeded
70
	 */
71
	public function checkCredentials($username, $password)
72
	{
73
		$request = $this->createBasicRequest();
74
		$this->_httpClient->setAuth($username, $password);
75
76
		$statusCode = $this->getResponseStatusCode($request);
77
		$this->_httpClient->clearAuth();
78
79
		return $statusCode !== 401;
80
	}
81
	
82
	/**
83
	 * @return string the hostname:port combination
84
	 */
85
	public function getHostInfo()
86
	{
87
		return Backend::normalizeAddress($this->_hostname).':'.$this->_port;
88
	}
89
90
	/**
91
	 * @return \Zend\Http\Request a base request object
92
	 */
93
	private function createBasicRequest()
94
	{
95
		$request = new \Zend\Http\Request();
96
		return $request->setUri('http://'.$this->getHostInfo().'/');
97
	}
98
	
99
	/**
100
	 * Dispatches the specified request and returns the response. If any 
101
	 * exceptions occur, null is returned
102
	 * @param \Zend\Http\Request $request the request
103
	 * @return \Zend\Http\Response the response, or null if the request failed
104
	 */
105
	private function silentDispatch($request)
106
	{
107
		try
108
		{
109
			return $this->_httpClient->dispatch($request);
110
		}
111
		catch (Exception $e)
112
		{
113
			unset($e);
114
			return null;
115
		}
116
	}
117
	
118
	/**
119
	 * Dispatches the specified request and returns the response status code
120
	 * @param \Zend\Http\Request $request the request
121
	 * @return int|false the response code, or false if the request failed
122
	 */
123
	private function getResponseStatusCode($request)
124
	{
125
		$response = $this->silentDispatch($request);
126
127
		if ($response)
0 ignored issues
show
$response is of type Zend\Http\Response, thus it always evaluated to true.
Loading history...
128
			return $response->getStatusCode();
129
		else
130
			return false;
131
	}
132
	
133
	/**
134
	 * Parses the actual realm from the value of the WWW-Authenticate header
135
	 * @param \Zend\Http\Header\WWWAuthenticate $authenticateHeader the header
136
	 * @return string the authentication realm (an empty string if it was 
137
	 * malformed)
138
	 */
139
	private function parseRealm($authenticateHeader)
140
	{
141
		$parts = explode('=', $authenticateHeader->value);
142
143
		// Sanity check, otherwise the rest of the method won't work
144
		if (count($parts) !== 2)
145
			return '';
146
147
		$realm = $parts[1];
148
149
		// Remove eventual citation marks
150
		if (strpos($realm, '"') !== false)
151
			return substr($realm, 1, strlen($realm) - 2);
152
		else
153
			return $realm;
154
	}
155
156
}
157