2 namespace wcf\system\io
;
3 use wcf\system\exception\SystemException
;
6 * The RemoteFile class opens a connection to a remote host as a file.
9 * @copyright 2001-2019 WoltLab GmbH
10 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
11 * @package WoltLabSuite\Core\System\Io
13 class RemoteFile
extends File
{
30 protected $errorNumber = 0;
36 protected $errorDesc = '';
39 * true if PHP supports SSL/TLS
42 private static $hasSSLSupport = null;
44 /** @noinspection PhpMissingParentConstructorInspection */
46 * Opens a new connection to a remote host.
49 * @param integer $port
50 * @param integer $timeout
51 * @param array $options
52 * @throws SystemException
54 public function __construct($host, $port, $timeout = 30, $options = []) {
58 if (!preg_match('/^[a-z0-9]+:/', $this->host
)) $this->host
= 'tcp://'.$this->host
;
60 $context = stream_context_create($options);
62 $this->resource = stream_socket_client($this->host
.':'.$this->port
, $this->errorNumber
, $this->errorDesc
, $timeout, STREAM_CLIENT_CONNECT
, $context);
63 if ($this->resource === false) {
64 throw new \
Exception('stream_socket_client returned false: ' . $this->errorDesc
, $this->errorNumber
);
67 catch (\Exception
$e) {
68 throw new SystemException('Can not connect to ' . $host, 0, $this->errorDesc
, $e);
71 stream_set_timeout($this->resource, $timeout);
75 * Returns the error number of the last error.
79 public function getErrorNumber() {
80 return $this->errorNumber
;
84 * Returns the error description of the last error.
88 public function getErrorDesc() {
89 return $this->errorDesc
;
93 * Switches TLS support for this connection.
94 * Usually used in combination with 'STARTTLS'
96 * @param boolean $enable Whether TLS support should be enabled
97 * @return boolean True on success, false otherwise
99 public function setTLS($enable) {
100 if (!$this->hasTLSSupport()) return false;
102 $cryptoType = STREAM_CRYPTO_METHOD_TLS_CLIENT
;
104 // PHP 5.6.8+ defines STREAM_CRYPTO_METHOD_TLS_CLIENT as STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT for BC reasons.
105 // STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT was introduced in PHP 5.6.8, but is not exposed to userland. Try to use
106 // it for forward compatibility.
108 // As of PHP 7.2+ STREAM_CRYPTO_METHOD_TLS_CLIENT is equivalent to STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT.
109 // see: https://wiki.php.net/rfc/improved-tls-constants
110 // see: https://github.com/php/php-src/blob/197cac65fdf712effb19ad3e40688ceb7ebc7f7d/main/streams/php_stream_transport.h#L173-L175
111 if (defined('STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT')) $cryptoType |
= STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT
;
113 // Add bits for all known TLS versions for the reasons above.
114 if (defined('STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT')) $cryptoType |
= STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT
;
115 if (defined('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT')) $cryptoType |
= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
;
116 if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) $cryptoType |
= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
;
117 if (defined('STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT')) $cryptoType |
= STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT
;
119 return stream_socket_enable_crypto($this->resource, $enable, $cryptoType);
123 * Returns whether TLS support is available.
127 public function hasTLSSupport() {
128 return function_exists('stream_socket_enable_crypto');
132 * Returns true if PHP supports SSL/TLS.
136 public static function supportsSSL() {
137 if (static::$hasSSLSupport === null) {
138 static::$hasSSLSupport = false;
140 $transports = stream_get_transports();
141 foreach ($transports as $transport) {
142 if (preg_match('~^(ssl(v[23])?|tls(v[0-9\.]+)?)$~', $transport)) {
143 static::$hasSSLSupport = true;
149 return static::$hasSSLSupport;
153 * Disables SSL/TLS support on runtime regardless if PHP is theoretically capable of it.
155 public static function disableSSL() {
156 static::$hasSSLSupport = false;