Passed
Push — master ( 23c80e...5008b1 )
by Malte
02:22
created

Protocol::createStream()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 9
c 2
b 0
f 0
dl 0
loc 16
rs 9.9666
cc 3
nc 3
nop 4
1
<?php
2
/*
3
* File: ImapProtocol.php
4
* Category: Protocol
5
* Author: M.Goldenbaum
6
* Created: 16.09.20 18:27
7
* Updated: -
8
*
9
* Description:
10
*  -
11
*/
12
13
namespace Webklex\PHPIMAP\Connection\Protocols;
14
15
use Webklex\PHPIMAP\Exceptions\ConnectionFailedException;
16
use Webklex\PHPIMAP\IMAP;
17
18
/**
19
 * Class Protocol
20
 *
21
 * @package Webklex\PHPIMAP\Connection\Protocols
22
 */
23
abstract class Protocol implements ProtocolInterface {
24
25
    /**
26
     * Default connection timeout in seconds
27
     */
28
    protected $connection_timeout = 30;
29
30
    /**
31
     * @var boolean
32
     */
33
    protected $debug = false;
34
35
    /**
36
     * @var false|resource
37
     */
38
    public $stream = false;
39
40
    /**
41
     * Connection encryption method
42
     * @var mixed $encryption
43
     */
44
    protected $encryption = false;
45
46
    /**
47
     * Set to false to ignore SSL certificate validation
48
     * @var bool
49
     */
50
    protected $cert_validation = true;
51
52
    /**
53
     * Proxy settings
54
     * @var array
55
     */
56
    protected $proxy = [
57
        'socket' => null,
58
        'request_fulluri' => false,
59
        'username' => null,
60
        'password' => null,
61
    ];
62
63
    /**
64
     * Get an available cryptographic method
65
     *
66
     * @return int
67
     */
68
    public function getCryptoMethod() {
69
        // Allow the best TLS version(s) we can
70
        $cryptoMethod = STREAM_CRYPTO_METHOD_TLS_CLIENT;
71
72
        // PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
73
        // so add them back in manually if we can
74
        if (defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT')) {
75
            $cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
76
        }elseif (defined('STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT')) {
77
            $cryptoMethod = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
78
        }
79
80
        return $cryptoMethod;
81
    }
82
83
    /**
84
     * Enable SSL certificate validation
85
     *
86
     * @return $this
87
     */
88
    public function enableCertValidation() {
89
        $this->cert_validation = true;
90
        return $this;
91
    }
92
93
    /**
94
     * Disable SSL certificate validation
95
     * @return $this
96
     */
97
    public function disableCertValidation() {
98
        $this->cert_validation = false;
99
        return $this;
100
    }
101
102
    /**
103
     * Set SSL certificate validation
104
     * @var int $cert_validation
105
     *
106
     * @return $this
107
     */
108
    public function setCertValidation($cert_validation) {
109
        $this->cert_validation = $cert_validation;
0 ignored issues
show
Documentation Bug introduced by
The property $cert_validation was declared of type boolean, but $cert_validation is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
110
        return $this;
111
    }
112
113
    /**
114
     * Should we validate SSL certificate?
115
     *
116
     * @return bool
117
     */
118
    public function getCertValidation() {
119
        return $this->cert_validation;
120
    }
121
122
    /**
123
     * Set connection proxy settings
124
     * @var array $options
125
     *
126
     * @return $this
127
     */
128
    public function setProxy($options) {
129
        foreach ($this->proxy as $key => $val) {
130
            if (isset($options[$key])) {
131
                $this->proxy[$key] = $options[$key];
132
            }
133
        }
134
135
        return $this;
136
    }
137
138
    /**
139
     * Get the current proxy settings
140
     *
141
     * @return array
142
     */
143
    public function getProxy() {
144
        return $this->proxy;
145
    }
146
147
    /**
148
     * Prepare socket options
149
     * @var string $transport
150
     *
151
     * @return array
152
     */
153
    private function defaultSocketOptions($transport) {
154
        $options = [];
155
        if ($this->encryption != false) {
156
            $options["ssl"] = [
157
                'verify_peer_name' => $this->getCertValidation(),
158
                'verify_peer'      => $this->getCertValidation(),
159
            ];
160
        }
161
162
        if ($this->proxy["socket"] != null) {
163
            $options[$transport]["proxy"] = $this->proxy["socket"];
164
            $options[$transport]["request_fulluri"] = $this->proxy["request_fulluri"];
165
166
            if ($this->proxy["username"] != null) {
167
                $auth = base64_encode($this->proxy["username"].':'.$this->proxy["password"]);
168
169
                $options[$transport]["header"] = [
170
                    "Proxy-Authorization: Basic $auth"
171
                ];
172
            }
173
        }
174
175
        return $options;
176
    }
177
178
    /**
179
     * Create a new resource stream
180
     * @param $transport
181
     * @param string $host hostname or IP address of IMAP server
182
     * @param int $port of IMAP server, default is 143 (993 for ssl)
183
     * @param int $timeout timeout in seconds for initiating session
184
     *
185
     * @return resource|boolean The socket created.
186
     * @throws ConnectionFailedException
187
     */
188
    protected function createStream($transport, $host, $port, $timeout) {
189
        $socket = "$transport://$host:$port";
190
        $stream = stream_socket_client($socket, $errno, $errstr, $timeout,
191
            STREAM_CLIENT_CONNECT,
192
            stream_context_create($this->defaultSocketOptions($transport))
193
        );
194
195
        if (!$stream) {
0 ignored issues
show
introduced by
$stream is of type resource, thus it always evaluated to false.
Loading history...
196
            throw new ConnectionFailedException($errstr, $errno);
197
        }
198
199
        if (false === stream_set_timeout($stream, $timeout)) {
200
            throw new ConnectionFailedException('Failed to set stream timeout');
201
        }
202
203
        return $stream;
204
    }
205
206
    /**
207
     * @return int
208
     */
209
    public function getConnectionTimeout() {
210
        return $this->connection_timeout;
211
    }
212
213
    /**
214
     * @param int $connection_timeout
215
     * @return Protocol
216
     */
217
    public function setConnectionTimeout($connection_timeout) {
218
        if ($connection_timeout !== null) {
0 ignored issues
show
introduced by
The condition $connection_timeout !== null is always true.
Loading history...
219
            $this->connection_timeout = $connection_timeout;
220
        }
221
        return $this;
222
    }
223
224
    /**
225
     * Get the UID key string
226
     * @param int|string $uid
227
     *
228
     * @return string
229
     */
230
    public function getUIDKey($uid) {
231
        if ($uid == IMAP::ST_UID || $uid == IMAP::FT_UID) {
232
            return "UID";
233
        }
234
        if (strlen($uid) > 0 && !is_numeric($uid)) {
235
            return (string)$uid;
236
        }
237
238
        return "";
239
    }
240
241
    public function buildUIDCommand($command, $uid) {
242
        return trim($this->getUIDKey($uid)." ".$command);
243
    }
244
245
}