This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||||
2 | // |
||||
3 | // +----------------------------------------------------------------------+ |
||||
4 | // | PHP Version 4 | |
||||
5 | // +----------------------------------------------------------------------+ |
||||
6 | // | Copyright (c) 1997-2003 The PHP Group | |
||||
7 | // +----------------------------------------------------------------------+ |
||||
8 | // | This source file is subject to version 2.02 of the PHP license, | |
||||
9 | // | that is bundled with this package in the file LICENSE, and is | |
||||
10 | // | available at through the world-wide-web at | |
||||
11 | // | https://www.php.net/license/2_02.txt. | |
||||
12 | // | If you did not receive a copy of the PHP license and are unable to | |
||||
13 | // | obtain it through the world-wide-web, please send a note to | |
||||
14 | // | [email protected] so we can mail you a copy immediately. | |
||||
15 | // +----------------------------------------------------------------------+ |
||||
16 | // | Author: Damian Alejandro Fernandez Sosa <[email protected]> | |
||||
17 | // +----------------------------------------------------------------------+ |
||||
18 | require_once XHELP_PEAR_PATH . '/Net/Socket.php'; |
||||
19 | |||||
20 | /** |
||||
21 | * Provides an implementation of the IMAP protocol using PEAR's |
||||
22 | * Net_Socket:: class. |
||||
23 | * |
||||
24 | * @author Damian Alejandro Fernandez Sosa <[email protected]> |
||||
25 | */ |
||||
26 | class Net_IMAPProtocol |
||||
27 | { |
||||
28 | /** |
||||
29 | * The auth methods this class support |
||||
30 | * @var array |
||||
31 | */ |
||||
32 | public $supportedAuthMethods = ['DIGEST-MD5', 'CRAM-MD5', 'LOGIN']; |
||||
33 | /** |
||||
34 | * The auth methods this class support |
||||
35 | * @var array |
||||
36 | */ |
||||
37 | public $supportedSASLAuthMethods = ['DIGEST-MD5', 'CRAM-MD5']; |
||||
38 | /** |
||||
39 | * _serverAuthMethods |
||||
40 | * @var bool |
||||
41 | */ |
||||
42 | public $_serverAuthMethods = null; |
||||
43 | /** |
||||
44 | * The the current mailbox |
||||
45 | * @var string |
||||
46 | */ |
||||
47 | public $currentMailbox = 'INBOX'; |
||||
48 | /** |
||||
49 | * The socket resource being used to connect to the IMAP server. |
||||
50 | * @var resource |
||||
51 | */ |
||||
52 | public $_socket = null; |
||||
53 | /** |
||||
54 | * To allow class debuging |
||||
55 | * @var bool |
||||
56 | */ |
||||
57 | public $_debug = false; |
||||
58 | public $dbgDialog = ''; |
||||
59 | /** |
||||
60 | * Command Number |
||||
61 | * @var int |
||||
62 | */ |
||||
63 | public $_cmd_counter = 1; |
||||
64 | /** |
||||
65 | * Command Number for IMAP commands |
||||
66 | * @var int |
||||
67 | */ |
||||
68 | public $_lastCmdID = 1; |
||||
69 | /** |
||||
70 | * Command Number |
||||
71 | * @var bool |
||||
72 | */ |
||||
73 | public $_unParsedReturn = false; |
||||
74 | /** |
||||
75 | * _connected: checks if there is a connection made to a imap server or not |
||||
76 | * @var bool |
||||
77 | */ |
||||
78 | public $_connected = false; |
||||
79 | /** |
||||
80 | * Capabilities |
||||
81 | * @var bool |
||||
82 | */ |
||||
83 | public $_serverSupportedCapabilities = null; |
||||
84 | /** |
||||
85 | * Use UTF-7 funcionallity |
||||
86 | * @var bool |
||||
87 | */ |
||||
88 | //var $_useUTF_7 = false; |
||||
89 | public $_useUTF_7 = true; |
||||
90 | |||||
91 | /** |
||||
92 | * Constructor |
||||
93 | * |
||||
94 | * Instantiates a new Net_IMAP object. |
||||
95 | * |
||||
96 | * @since 1.0 |
||||
97 | */ |
||||
98 | public function __construct() |
||||
99 | { |
||||
100 | $this->_socket = new Net_Socket(); |
||||
0 ignored issues
–
show
|
|||||
101 | |||||
102 | /* |
||||
103 | * Include the Auth_SASL package. If the package is not available, |
||||
104 | * we disable the authentication methods that depend upon it. |
||||
105 | */ |
||||
106 | |||||
107 | if (false === (@require_once __DIR__ . '/Auth/SASL.php')) { |
||||
108 | foreach ($this->supportedSASLAuthMethods as $SASLMethod) { |
||||
109 | $pos = array_search($SASLMethod, $this->supportedAuthMethods, true); |
||||
110 | unset($this->supportedAuthMethods[$pos]); |
||||
111 | } |
||||
112 | } |
||||
113 | } |
||||
114 | |||||
115 | /** |
||||
116 | * Attempt to connect to the IMAP server. |
||||
117 | * |
||||
118 | * @param string $host |
||||
119 | * @param int $port |
||||
120 | * @return bool|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
121 | * kind of failure, or true on success. |
||||
122 | * @since 1.0 |
||||
123 | */ |
||||
124 | public function cmdConnect(string $host = 'localhost', int $port = 143) |
||||
125 | { |
||||
126 | if ($this->_connected) { |
||||
127 | return new PEAR_Error('already connected, logout first!'); |
||||
128 | } |
||||
129 | if (PEAR::isError($this->_socket->connect($host, $port))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
130 | return new PEAR_Error('unable to open socket'); |
||||
131 | } |
||||
132 | if (PEAR::isError($this->_getRawResponse())) { |
||||
133 | return new PEAR_Error('unable to open socket'); |
||||
134 | } |
||||
135 | $this->_connected = true; |
||||
136 | |||||
137 | return true; |
||||
138 | } |
||||
139 | |||||
140 | /** |
||||
141 | * get the cmd ID |
||||
142 | * |
||||
143 | * @return string Returns the CmdID and increment the counter |
||||
144 | * |
||||
145 | * @since 1.0 |
||||
146 | */ |
||||
147 | public function _getCmdId() |
||||
148 | { |
||||
149 | $this->_lastCmdID = 'A000' . $this->_cmd_counter; |
||||
0 ignored issues
–
show
The property
$_lastCmdID was declared of type integer , but 'A000' . $this->_cmd_counter is of type string . 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;
![]() |
|||||
150 | $this->_cmd_counter++; |
||||
151 | |||||
152 | return $this->_lastCmdID; |
||||
153 | } |
||||
154 | |||||
155 | /** |
||||
156 | * get the last cmd ID |
||||
157 | * |
||||
158 | * @return int Returns the last cmdId |
||||
159 | * |
||||
160 | * @since 1.0 |
||||
161 | */ |
||||
162 | public function getLastCmdId(): int |
||||
163 | { |
||||
164 | return $this->_lastCmdID; |
||||
165 | } |
||||
166 | |||||
167 | /** |
||||
168 | * get current mailbox name |
||||
169 | * |
||||
170 | * @return string Returns the current mailbox |
||||
171 | * |
||||
172 | * @since 1.0 |
||||
173 | */ |
||||
174 | public function getCurrentMailbox(): string |
||||
175 | { |
||||
176 | return $this->currentMailbox; |
||||
177 | } |
||||
178 | |||||
179 | /** |
||||
180 | * Sets the debuging information on or off |
||||
181 | * |
||||
182 | * @param mixed $debug |
||||
183 | * |
||||
184 | * @since 1.0 |
||||
185 | */ |
||||
186 | public function setDebug($debug = true): void |
||||
187 | { |
||||
188 | $this->_debug = $debug; |
||||
189 | } |
||||
190 | |||||
191 | /** |
||||
192 | * @return string |
||||
193 | */ |
||||
194 | public function getDebugDialog(): string |
||||
195 | { |
||||
196 | return $this->dbgDialog; |
||||
197 | } |
||||
198 | |||||
199 | /** |
||||
200 | * Send the given string of data to the server. |
||||
201 | * |
||||
202 | * @param string $data The string of data to send. |
||||
203 | * |
||||
204 | * @return bool|\PEAR_Error True on success or a PEAR_Error object on failure. |
||||
205 | * |
||||
206 | * @since 1.0 |
||||
207 | */ |
||||
208 | public function _send(string $data) |
||||
209 | { |
||||
210 | if ($this->_socket->eof()) { |
||||
211 | return new PEAR_Error('Failed to write to socket: (connection lost!) '); |
||||
212 | } |
||||
213 | if (PEAR::isError($error = $this->_socket->write($data))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
214 | return new PEAR_Error('Failed to write to socket: ' . $error->getMessage()); |
||||
215 | } |
||||
216 | |||||
217 | if ($this->_debug) { |
||||
218 | // C: means this data was sent by the client (this class) |
||||
219 | echo "C: $data"; |
||||
220 | $this->dbgDialog .= "C: $data"; |
||||
221 | } |
||||
222 | |||||
223 | return true; |
||||
224 | } |
||||
225 | |||||
226 | /** |
||||
227 | * Receive the given string of data from the server. |
||||
228 | * |
||||
229 | * @return mixed a line of response on success or a PEAR_Error object on failure. |
||||
230 | * |
||||
231 | * @since 1.0 |
||||
232 | */ |
||||
233 | public function _recvLn() |
||||
234 | { |
||||
235 | if (PEAR::isError($this->lastline = $this->_socket->gets(8192))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
236 | return new PEAR_Error('Failed to write to socket: ' . $this->lastline->getMessage()); |
||||
237 | } |
||||
238 | if ($this->_debug) { |
||||
239 | // S: means this data was sent by the IMAP Server |
||||
240 | echo 'S: ' . $this->lastline . ''; |
||||
241 | $this->dbgDialog .= 'S: ' . $this->lastline . ''; |
||||
242 | } |
||||
243 | if ('' === $this->lastline) { |
||||
244 | return new PEAR_Error('Failed to receive from the socket: '); |
||||
245 | } |
||||
246 | |||||
247 | return $this->lastline; |
||||
248 | } |
||||
249 | |||||
250 | /** |
||||
251 | * Send a command to the server with an optional string of arguments. |
||||
252 | * A carriage return / linefeed (CRLF) sequence will be appended to each |
||||
253 | * command string before it is sent to the IMAP server. |
||||
254 | * |
||||
255 | * @param string $commandId The IMAP cmdID to send to the server. |
||||
256 | * @param string $command The IMAP command to send to the server. |
||||
257 | * @param string $args A string of optional arguments to append |
||||
258 | * to the command. |
||||
259 | * |
||||
260 | * @return bool|\PEAR_Error The result of the _send() call. |
||||
261 | * |
||||
262 | * @since 1.0 |
||||
263 | */ |
||||
264 | public function _putCMD(string $commandId, string $command, string $args = '') |
||||
265 | { |
||||
266 | if (!empty($args)) { |
||||
267 | return $this->_send($commandId . ' ' . $command . ' ' . $args . "\r\n"); |
||||
268 | } |
||||
269 | |||||
270 | return $this->_send($commandId . ' ' . $command . "\r\n"); |
||||
271 | } |
||||
272 | |||||
273 | /** |
||||
274 | * Get a response from the server with an optional string of commandID. |
||||
275 | * A carriage return / linefeed (CRLF) sequence will be appended to each |
||||
276 | * command string before it is sent to the IMAP server. |
||||
277 | * |
||||
278 | * @param string $commandId |
||||
279 | * @return string The result response. |
||||
280 | */ |
||||
281 | public function _getRawResponse(string $commandId = '*'): string |
||||
282 | { |
||||
283 | $arguments = ''; |
||||
284 | while (!PEAR::isError($this->_recvLn())) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
285 | $reply_code = strtok($this->lastline, ' '); |
||||
286 | $arguments .= $this->lastline; |
||||
287 | if (!strcmp($commandId, $reply_code)) { |
||||
288 | return $arguments; |
||||
289 | } |
||||
290 | } |
||||
291 | |||||
292 | return $arguments; |
||||
293 | } |
||||
294 | |||||
295 | /** |
||||
296 | * get the "returning of the unparsed response" feature status |
||||
297 | * |
||||
298 | * @return bool return if the unparsed response is returned or not |
||||
299 | * |
||||
300 | * @since 1.0 |
||||
301 | */ |
||||
302 | public function getUnparsedResponse(): bool |
||||
303 | { |
||||
304 | return $this->_unParsedReturn; |
||||
305 | } |
||||
306 | |||||
307 | /** |
||||
308 | * set the "returning of the unparsed response" feature on or off |
||||
309 | * |
||||
310 | * @param bool $status : true: feature is on |
||||
311 | * |
||||
312 | * @since 1.0 |
||||
313 | */ |
||||
314 | public function setUnparsedResponse(bool $status): void |
||||
315 | { |
||||
316 | $this->_unParsedReturn = $status; |
||||
317 | } |
||||
318 | |||||
319 | /** |
||||
320 | * Attempt to login to the iMAP server. |
||||
321 | * |
||||
322 | * @param mixed $uid |
||||
323 | * @param mixed $pwd |
||||
324 | * |
||||
325 | * @return array Returns an array containing the response |
||||
326 | * |
||||
327 | * @since 1.0 |
||||
328 | */ |
||||
329 | public function cmdLogin($uid, $pwd) |
||||
330 | { |
||||
331 | $param = "\"$uid\" \"$pwd\""; |
||||
332 | |||||
333 | return $this->_genericCommand('LOGIN', $param); |
||||
0 ignored issues
–
show
|
|||||
334 | } |
||||
335 | |||||
336 | /** |
||||
337 | * Attempt to authenticate to the iMAP server. |
||||
338 | * @param mixed $uid |
||||
339 | * @param mixed $pwd |
||||
340 | * @param null|mixed $userMethod |
||||
341 | * |
||||
342 | * @return array|\PEAR_Error Returns an array containing the response |
||||
343 | * |
||||
344 | * @since 1.0 |
||||
345 | */ |
||||
346 | public function cmdAuthenticate($uid, $pwd, $userMethod = null) |
||||
347 | { |
||||
348 | if (!$this->_connected) { |
||||
349 | return new PEAR_Error('not connected!'); |
||||
350 | } |
||||
351 | |||||
352 | $cmdid = $this->_getCmdId(); |
||||
353 | |||||
354 | if (PEAR::isError($method = $this->_getBestAuthMethod($userMethod))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
355 | return $method; |
||||
356 | } |
||||
357 | |||||
358 | switch ($method) { |
||||
359 | case 'DIGEST-MD5': |
||||
360 | $result = $this->_authDigest_MD5($uid, $pwd, $cmdid); |
||||
0 ignored issues
–
show
$cmdid of type string is incompatible with the type integer expected by parameter $cmdid of Net_IMAPProtocol::_authDigest_MD5() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
361 | break; |
||||
362 | case 'CRAM-MD5': |
||||
363 | $result = $this->_authCRAM_MD5($uid, $pwd, $cmdid); |
||||
0 ignored issues
–
show
$cmdid of type string is incompatible with the type integer expected by parameter $cmdid of Net_IMAPProtocol::_authCRAM_MD5() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
364 | break; |
||||
365 | case 'LOGIN': |
||||
366 | $result = $this->_authLOGIN($uid, $pwd, $cmdid); |
||||
0 ignored issues
–
show
$cmdid of type string is incompatible with the type integer expected by parameter $cmdid of Net_IMAPProtocol::_authLOGIN() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
367 | break; |
||||
368 | default: |
||||
369 | $result = new PEAR_Error("$method is not a supported authentication method"); |
||||
370 | break; |
||||
371 | } |
||||
372 | |||||
373 | $args = $this->_getRawResponse($cmdid); |
||||
374 | |||||
375 | return $this->_genericImapResponseParser($args, $cmdid); |
||||
376 | } |
||||
377 | |||||
378 | /* Authenticates the user using the DIGEST-MD5 method. |
||||
379 | * |
||||
380 | * @param string $uid The userid to authenticate as. |
||||
381 | * @param string $pwd The password to authenticate with. |
||||
382 | * @param string $cmdid The cmdID. |
||||
383 | * |
||||
384 | * @return array Returns an array containing the response |
||||
385 | * |
||||
386 | * @access private |
||||
387 | * @since 1.0 |
||||
388 | */ |
||||
389 | |||||
390 | /** |
||||
391 | * @param int $uid |
||||
392 | * @param string $pwd |
||||
393 | * @param int $cmdid |
||||
394 | * @return bool|mixed|\PEAR_Error |
||||
395 | */ |
||||
396 | public function _authDigest_MD5(int $uid, string $pwd, int $cmdid) |
||||
397 | { |
||||
398 | if (PEAR::isError($error = $this->_putCMD($cmdid, 'AUTHENTICATE', 'DIGEST-MD5'))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
399 | return $error; |
||||
400 | } |
||||
401 | |||||
402 | if (PEAR::isError($args = $this->_recvLn())) { |
||||
403 | return $args; |
||||
404 | } |
||||
405 | |||||
406 | $this->_getNextToken($args, $plus); |
||||
407 | |||||
408 | $this->_getNextToken($args, $space); |
||||
409 | |||||
410 | $this->_getNextToken($args, $challenge); |
||||
411 | |||||
412 | $challenge = base64_decode($challenge, true); |
||||
413 | |||||
414 | $digest = &Auth_SASL::factory('digestmd5'); |
||||
0 ignored issues
–
show
The type
Auth_SASL was not found. Maybe you did not declare it correctly or list all dependencies?
The issue could also be caused by a filter entry in the build configuration.
If the path has been excluded in your configuration, e.g. filter:
dependency_paths: ["lib/*"]
For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths ![]() |
|||||
415 | |||||
416 | $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, 'localhost', 'imap')); |
||||
417 | |||||
418 | if (PEAR::isError($error = $this->_send("$auth_str\r\n"))) { |
||||
419 | return $error; |
||||
420 | } |
||||
421 | |||||
422 | if (PEAR::isError($args = $this->_recvLn())) { |
||||
423 | return $args; |
||||
424 | } |
||||
425 | /* |
||||
426 | * We don't use the protocol's third step because IMAP doesn't allow |
||||
427 | * subsequent authentication, so we just silently ignore it. |
||||
428 | */ |
||||
429 | if (PEAR::isError($error = $this->_send("\r\n"))) { |
||||
430 | return $error; |
||||
431 | } |
||||
432 | } |
||||
433 | |||||
434 | /* Authenticates the user using the CRAM-MD5 method. |
||||
435 | * |
||||
436 | * @param string $uid The userid to authenticate as. |
||||
437 | * @param string $pwd The password to authenticate with. |
||||
438 | * @param string $cmdid The cmdID. |
||||
439 | * |
||||
440 | * @return array Returns an array containing the response |
||||
441 | * |
||||
442 | * @access private |
||||
443 | * @since 1.0 |
||||
444 | */ |
||||
445 | |||||
446 | /** |
||||
447 | * @param int $uid |
||||
448 | * @param string $pwd |
||||
449 | * @param int $cmdid |
||||
450 | * @return bool|mixed|\PEAR_Error |
||||
451 | */ |
||||
452 | public function _authCRAM_MD5(int $uid, string $pwd, int $cmdid) |
||||
453 | { |
||||
454 | if (PEAR::isError($error = $this->_putCMD($cmdid, 'AUTHENTICATE', 'CRAM-MD5'))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
455 | return $error; |
||||
456 | } |
||||
457 | |||||
458 | if (PEAR::isError($args = $this->_recvLn())) { |
||||
459 | return $args; |
||||
460 | } |
||||
461 | |||||
462 | $this->_getNextToken($args, $plus); |
||||
463 | |||||
464 | $this->_getNextToken($args, $space); |
||||
465 | |||||
466 | $this->_getNextToken($args, $challenge); |
||||
467 | |||||
468 | $challenge = base64_decode($challenge, true); |
||||
469 | |||||
470 | $cram = &Auth_SASL::factory('crammd5'); |
||||
471 | |||||
472 | $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); |
||||
473 | |||||
474 | if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) { |
||||
475 | return $error; |
||||
476 | } |
||||
477 | } |
||||
478 | |||||
479 | /* Authenticates the user using the LOGIN method. |
||||
480 | * |
||||
481 | * @param string $uid The userid to authenticate as. |
||||
482 | * @param string $pwd The password to authenticate with. |
||||
483 | * @param string $cmdid The cmdID. |
||||
484 | * |
||||
485 | * @return array Returns an array containing the response |
||||
486 | * |
||||
487 | * @access private |
||||
488 | * @since 1.0 |
||||
489 | */ |
||||
490 | |||||
491 | /** |
||||
492 | * @param int $uid |
||||
493 | * @param string $pwd |
||||
494 | * @param int $cmdid |
||||
495 | * @return bool|mixed|\PEAR_Error |
||||
496 | */ |
||||
497 | public function _authLOGIN(int $uid, string $pwd, int $cmdid) |
||||
498 | { |
||||
499 | if (PEAR::isError($error = $this->_putCMD($cmdid, 'AUTHENTICATE', 'LOGIN'))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
500 | return $error; |
||||
501 | } |
||||
502 | |||||
503 | if (PEAR::isError($args = $this->_recvLn())) { |
||||
504 | return $args; |
||||
505 | } |
||||
506 | |||||
507 | $this->_getNextToken($args, $plus); |
||||
508 | |||||
509 | $this->_getNextToken($args, $space); |
||||
510 | |||||
511 | $this->_getNextToken($args, $challenge); |
||||
512 | |||||
513 | $challenge = base64_decode($challenge, true); |
||||
0 ignored issues
–
show
|
|||||
514 | |||||
515 | $auth_str = base64_encode((string)$uid); |
||||
516 | |||||
517 | if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) { |
||||
518 | return $error; |
||||
519 | } |
||||
520 | |||||
521 | if (PEAR::isError($args = $this->_recvLn())) { |
||||
522 | return $args; |
||||
523 | } |
||||
524 | |||||
525 | $auth_str = base64_encode((string)$pwd); |
||||
526 | |||||
527 | if (PEAR::isError($error = $this->_send($auth_str . "\r\n"))) { |
||||
528 | return $error; |
||||
529 | } |
||||
530 | } |
||||
531 | |||||
532 | /** |
||||
533 | * Returns the name of the best authentication method that the server |
||||
534 | * has advertised. |
||||
535 | * |
||||
536 | * @param string|null $userMethod |
||||
537 | * @return mixed Returns a string containing the name of the best |
||||
538 | * supported authentication method or a PEAR_Error object |
||||
539 | * if a failure condition is encountered. |
||||
540 | * @since 1.0 |
||||
541 | */ |
||||
542 | public function _getBestAuthMethod(string $userMethod = null) |
||||
543 | { |
||||
544 | $this->cmdCapability(); |
||||
545 | |||||
546 | if (null !== $userMethod) { |
||||
547 | $methods = []; |
||||
548 | |||||
549 | $methods[] = $userMethod; |
||||
550 | } else { |
||||
551 | $methods = $this->supportedAuthMethods; |
||||
552 | } |
||||
553 | |||||
554 | if ((null !== $methods) && (null !== $this->_serverAuthMethods)) { |
||||
555 | foreach ($methods as $method) { |
||||
556 | if (in_array($method, $this->_serverAuthMethods, true)) { |
||||
0 ignored issues
–
show
$this->_serverAuthMethods of type boolean is incompatible with the type array expected by parameter $haystack of in_array() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
557 | return $method; |
||||
558 | } |
||||
559 | } |
||||
560 | $serverMethods = implode(',', $this->_serverAuthMethods); |
||||
0 ignored issues
–
show
$this->_serverAuthMethods of type boolean is incompatible with the type array expected by parameter $pieces of implode() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
561 | $myMethods = implode(',', $this->supportedAuthMethods); |
||||
562 | |||||
563 | return new PEAR_Error("$method NOT supported authentication method!. This IMAP server " . "supports these methods: $serverMethods, but I support $myMethods"); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
564 | } |
||||
565 | |||||
566 | return new PEAR_Error("This IMAP server don't support any Auth methods"); |
||||
567 | } |
||||
568 | |||||
569 | /** |
||||
570 | * Attempt to disconnect from the iMAP server. |
||||
571 | * |
||||
572 | * @return array|string Returns an array containing the response |
||||
573 | * |
||||
574 | * @since 1.0 |
||||
575 | */ |
||||
576 | public function cmdLogout() |
||||
577 | { |
||||
578 | if (!$this->_connected) { |
||||
579 | return new PEAR_Error('not connected!'); |
||||
0 ignored issues
–
show
|
|||||
580 | } |
||||
581 | |||||
582 | $cmdid = $this->_getCmdId(); |
||||
583 | if (PEAR::isError($error = $this->_putCMD($cmdid, 'LOGOUT'))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
584 | return $error; |
||||
0 ignored issues
–
show
|
|||||
585 | } |
||||
586 | if (PEAR::isError($args = $this->_getRawResponse())) { |
||||
587 | return $args; |
||||
588 | } |
||||
589 | if (PEAR::isError($this->_socket->disconnect())) { |
||||
590 | return new PEAR_Error('socket disconnect failed'); |
||||
0 ignored issues
–
show
|
|||||
591 | } |
||||
592 | |||||
593 | return $args; |
||||
594 | // not for now |
||||
595 | //return $this->_genericImapResponseParser($args,$cmdid); |
||||
596 | } |
||||
597 | |||||
598 | /** |
||||
599 | * Send the NOOP command. |
||||
600 | * |
||||
601 | * @return array Returns an array containing the response |
||||
602 | * |
||||
603 | * @since 1.0 |
||||
604 | */ |
||||
605 | public function cmdNoop() |
||||
606 | { |
||||
607 | return $this->_genericCommand('NOOP'); |
||||
0 ignored issues
–
show
|
|||||
608 | } |
||||
609 | |||||
610 | /** |
||||
611 | * Send the CHECK command. |
||||
612 | * |
||||
613 | * @return array Returns an array containing the response |
||||
614 | * |
||||
615 | * @since 1.0 |
||||
616 | */ |
||||
617 | public function cmdCheck() |
||||
618 | { |
||||
619 | return $this->_genericCommand('CHECK'); |
||||
0 ignored issues
–
show
|
|||||
620 | } |
||||
621 | |||||
622 | /** |
||||
623 | * Send the Select Mailbox Command |
||||
624 | * |
||||
625 | * @param mixed $mailbox |
||||
626 | * |
||||
627 | * @return array Returns an array containing the response |
||||
628 | * |
||||
629 | * @since 1.0 |
||||
630 | */ |
||||
631 | public function cmdSelect($mailbox) |
||||
632 | { |
||||
633 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
634 | if (!PEAR::isError($ret = $this->_genericCommand('SELECT', $mailbox_name))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
635 | $this->currentMailbox = $mailbox; |
||||
636 | } |
||||
637 | |||||
638 | return $ret; |
||||
0 ignored issues
–
show
|
|||||
639 | } |
||||
640 | |||||
641 | /** |
||||
642 | * Send the EXAMINE Mailbox Command |
||||
643 | * |
||||
644 | * @param mixed $mailbox |
||||
645 | * @return array Returns an array containing the response |
||||
646 | * |
||||
647 | * @since 1.0 |
||||
648 | */ |
||||
649 | public function cmdExamine($mailbox): array |
||||
650 | { |
||||
651 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
652 | $ret = $this->_genericCommand('EXAMINE', $mailbox_name); |
||||
653 | $parsed = ''; |
||||
654 | if (isset($ret['PARSED'])) { |
||||
655 | foreach ($ret['PARSED'] as $i => $iValue) { |
||||
656 | $command = $ret['PARSED'][$i]['EXT']; |
||||
657 | $parsed[key($command)] = $command[key($command)]; |
||||
658 | } |
||||
659 | } |
||||
660 | |||||
661 | return ['PARSED' => $parsed, 'RESPONSE' => $ret['RESPONSE']]; |
||||
662 | } |
||||
663 | |||||
664 | /** |
||||
665 | * Send the CREATE Mailbox Command |
||||
666 | * |
||||
667 | * @param mixed $mailbox |
||||
668 | * @return array Returns an array containing the response |
||||
669 | * |
||||
670 | * @since 1.0 |
||||
671 | */ |
||||
672 | public function cmdCreate($mailbox) |
||||
673 | { |
||||
674 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
675 | |||||
676 | return $this->_genericCommand('CREATE', $mailbox_name); |
||||
0 ignored issues
–
show
|
|||||
677 | } |
||||
678 | |||||
679 | /** |
||||
680 | * Send the RENAME Mailbox Command |
||||
681 | * |
||||
682 | * @param mixed $mailbox |
||||
683 | * @param mixed $new_mailbox |
||||
684 | * |
||||
685 | * @return array Returns an array containing the response |
||||
686 | * |
||||
687 | * @since 1.0 |
||||
688 | */ |
||||
689 | public function cmdRename($mailbox, $new_mailbox) |
||||
690 | { |
||||
691 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
692 | $new_mailbox_name = sprintf('"%s"', $this->utf_7_encode($new_mailbox)); |
||||
693 | |||||
694 | return $this->_genericCommand('RENAME', "$mailbox_name $new_mailbox_name"); |
||||
0 ignored issues
–
show
|
|||||
695 | } |
||||
696 | |||||
697 | /** |
||||
698 | * Send the DELETE Mailbox Command |
||||
699 | * |
||||
700 | * @param mixed $mailbox |
||||
701 | * |
||||
702 | * @return array Returns an array containing the response |
||||
703 | * |
||||
704 | * @since 1.0 |
||||
705 | */ |
||||
706 | public function cmdDelete($mailbox) |
||||
707 | { |
||||
708 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
709 | |||||
710 | return $this->_genericCommand('DELETE', $mailbox_name); |
||||
0 ignored issues
–
show
|
|||||
711 | } |
||||
712 | |||||
713 | /** |
||||
714 | * Send the SUSCRIBE Mailbox Command |
||||
715 | * |
||||
716 | * @param mixed $mailbox |
||||
717 | * |
||||
718 | * @return array Returns an array containing the response |
||||
719 | * |
||||
720 | * @since 1.0 |
||||
721 | */ |
||||
722 | public function cmdSubscribe($mailbox) |
||||
723 | { |
||||
724 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
725 | |||||
726 | return $this->_genericCommand('SUBSCRIBE', $mailbox_name); |
||||
0 ignored issues
–
show
|
|||||
727 | } |
||||
728 | |||||
729 | /** |
||||
730 | * Send the UNSUSCRIBE Mailbox Command |
||||
731 | * |
||||
732 | * @param string $mailbox |
||||
733 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
734 | * kind of failure, or true on success. |
||||
735 | * @since 1.0 |
||||
736 | */ |
||||
737 | public function cmdUnsubscribe(string $mailbox) |
||||
738 | { |
||||
739 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
740 | |||||
741 | return $this->_genericCommand('UNSUBSCRIBE', $mailbox_name); |
||||
742 | } |
||||
743 | |||||
744 | /** |
||||
745 | * Send the FETCH Command |
||||
746 | * |
||||
747 | * @param mixed $msgset |
||||
748 | * @param mixed $fetchparam |
||||
749 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
750 | * kind of failure, or true on success. |
||||
751 | * @since 1.0 |
||||
752 | */ |
||||
753 | public function cmdFetch($msgset, $fetchparam) |
||||
754 | { |
||||
755 | return $this->_genericCommand('FETCH', "$msgset $fetchparam"); |
||||
756 | } |
||||
757 | |||||
758 | /** |
||||
759 | * Send the CAPABILITY Command |
||||
760 | * |
||||
761 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
762 | * kind of failure, or true on success. |
||||
763 | * @since 1.0 |
||||
764 | */ |
||||
765 | public function cmdCapability() |
||||
766 | { |
||||
767 | $ret = $this->_genericCommand('CAPABILITY'); |
||||
768 | |||||
769 | if (isset($ret['PARSED'])) { |
||||
770 | $ret['PARSED'] = $ret['PARSED'][0]['EXT']['CAPABILITY']; |
||||
771 | //fill the $this->_serverAuthMethods and $this->_serverSupportedCapabilities arrays |
||||
772 | foreach ($ret['PARSED']['CAPABILITIES'] as $auth_method) { |
||||
773 | if (0 === mb_stripos($auth_method, 'AUTH=')) { |
||||
774 | $this->_serverAuthMethods[] = mb_substr($auth_method, 5); |
||||
775 | } |
||||
776 | } |
||||
777 | // Keep the capabilities response to use ir later |
||||
778 | $this->_serverSupportedCapabilities = $ret['PARSED']['CAPABILITIES']; |
||||
779 | } |
||||
780 | |||||
781 | return $ret; |
||||
782 | } |
||||
783 | |||||
784 | /** |
||||
785 | * Send the STATUS Mailbox Command |
||||
786 | * |
||||
787 | * @param string $mailbox the mailbox name |
||||
788 | * @param string $request the request status it could be: |
||||
789 | * MESSAGES | RECENT | UIDNEXT |
||||
790 | * UIDVALIDITY | UNSEEN |
||||
791 | * @return array Returns a Parsed Response |
||||
792 | * |
||||
793 | * @since 1.0 |
||||
794 | */ |
||||
795 | public function cmdStatus(string $mailbox, string $request) |
||||
796 | { |
||||
797 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
798 | |||||
799 | if ('MESSAGES' !== $request && 'RECENT' !== $request && 'UIDNEXT' !== $request |
||||
800 | && 'UIDVALIDITY' !== $request |
||||
801 | && 'UNSEEN' !== $request) { |
||||
802 | // TODO: fix this error! |
||||
803 | $this->_prot_error("request '$request' is invalid! see RFC2060!!!!", __LINE__, __FILE__, false); |
||||
804 | } |
||||
805 | $ret = $this->_genericCommand('STATUS', "$mailbox_name ($request)"); |
||||
806 | if (isset($ret['PARSED'])) { |
||||
807 | $ret['PARSED'] = $ret['PARSED'][count($ret['PARSED']) - 1]['EXT']; |
||||
808 | } |
||||
809 | |||||
810 | return $ret; |
||||
0 ignored issues
–
show
|
|||||
811 | } |
||||
812 | |||||
813 | /** |
||||
814 | * Send the LIST Command |
||||
815 | * |
||||
816 | * @param string $mailbox_base |
||||
817 | * @param string $mailbox |
||||
818 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
819 | * kind of failure, or true on success. |
||||
820 | * @since 1.0 |
||||
821 | */ |
||||
822 | public function cmdList(string $mailbox_base, string $mailbox) |
||||
823 | { |
||||
824 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
825 | $mailbox_base = sprintf('"%s"', $this->utf_7_encode($mailbox_base)); |
||||
826 | |||||
827 | return $this->_genericCommand('LIST', "$mailbox_base $mailbox_name"); |
||||
828 | } |
||||
829 | |||||
830 | /** |
||||
831 | * Send the LSUB Command |
||||
832 | * |
||||
833 | * @param string $mailbox_base |
||||
834 | * @param string $mailbox |
||||
835 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
836 | * kind of failure, or true on success. |
||||
837 | * @since 1.0 |
||||
838 | */ |
||||
839 | public function cmdLsub(string $mailbox_base, string $mailbox) |
||||
840 | { |
||||
841 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
842 | $mailbox_base = sprintf('"%s"', $this->utf_7_encode($mailbox_base)); |
||||
843 | |||||
844 | return $this->_genericCommand('LSUB', "$mailbox_base $mailbox_name"); |
||||
845 | } |
||||
846 | |||||
847 | /** |
||||
848 | * Send the APPEND Command |
||||
849 | * |
||||
850 | * @param string $mailbox |
||||
851 | * @param string $msg |
||||
852 | * @param string $flags_list |
||||
853 | * @param string $time |
||||
854 | * @return mixed Returns a PEAR_Error with an error message on any |
||||
855 | * kind of failure, or true on success. |
||||
856 | * @since 1.0 |
||||
857 | */ |
||||
858 | public function cmdAppend(string $mailbox, string $msg, string $flags_list = '', string $time = '') |
||||
859 | { |
||||
860 | if (!$this->_connected) { |
||||
861 | return new PEAR_Error('not connected!'); |
||||
862 | } |
||||
863 | |||||
864 | $cmdid = $this->_getCmdId(); |
||||
865 | $msg_size = mb_strlen($msg); |
||||
866 | |||||
867 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
868 | // TODO: |
||||
869 | // Falta el codigo para que flags list y time hagan algo!! |
||||
870 | if (true === $this->hasCapability('LITERAL+')) { |
||||
871 | $param = sprintf("%s %s%s{%s+}\r\n%s", $mailbox_name, $flags_list, $time, $msg_size, $msg); |
||||
872 | if (PEAR::isError($error = $this->_putCMD($cmdid, 'APPEND', $param))) { |
||||
0 ignored issues
–
show
The method
PEAR::isError() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
873 | return $error; |
||||
874 | } |
||||
875 | } else { |
||||
876 | $param = sprintf("%s %s%s{%s}\r\n", $mailbox_name, $flags_list, $time, $msg_size); |
||||
877 | if (PEAR::isError($error = $this->_putCMD($cmdid, 'APPEND', $param))) { |
||||
878 | return $error; |
||||
879 | } |
||||
880 | if (PEAR::isError($error = $this->_recvLn())) { |
||||
881 | return $error; |
||||
882 | } |
||||
883 | |||||
884 | if (PEAR::isError($error = $this->_send($msg))) { |
||||
885 | return $error; |
||||
886 | } |
||||
887 | } |
||||
888 | |||||
889 | $args = $this->_getRawResponse($cmdid); |
||||
890 | $ret = $this->_genericImapResponseParser($args, $cmdid); |
||||
891 | |||||
892 | return $ret; |
||||
893 | } |
||||
894 | |||||
895 | /** |
||||
896 | * Send the CLOSE command. |
||||
897 | * |
||||
898 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
899 | * kind of failure, or true on success. |
||||
900 | * @since 1.0 |
||||
901 | */ |
||||
902 | public function cmdClose() |
||||
903 | { |
||||
904 | return $this->_genericCommand('CLOSE'); |
||||
905 | } |
||||
906 | |||||
907 | /** |
||||
908 | * Send the EXPUNGE command. |
||||
909 | * |
||||
910 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
911 | * kind of failure, or true on success. |
||||
912 | * @since 1.0 |
||||
913 | */ |
||||
914 | public function cmdExpunge() |
||||
915 | { |
||||
916 | $ret = $this->_genericCommand('EXPUNGE'); |
||||
917 | |||||
918 | if (isset($ret['PARSED'])) { |
||||
919 | $parsed = $ret['PARSED']; |
||||
920 | unset($ret['PARSED']); |
||||
921 | foreach ($parsed as $command) { |
||||
922 | if ('EXPUNGE' === \mb_strtoupper($command['COMMAND'])) { |
||||
923 | $ret['PARSED'][$command['COMMAND']][] = $command['NRO']; |
||||
924 | } else { |
||||
925 | $ret['PARSED'][$command['COMMAND']] = $command['NRO']; |
||||
926 | } |
||||
927 | } |
||||
928 | } |
||||
929 | |||||
930 | return $ret; |
||||
931 | } |
||||
932 | |||||
933 | /** |
||||
934 | * Send the SEARCH command. |
||||
935 | * |
||||
936 | * @param string $search_cmd |
||||
937 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
938 | * kind of failure, or true on success. |
||||
939 | * @since 1.0 |
||||
940 | */ |
||||
941 | public function cmdSearch($search_cmd) |
||||
942 | { |
||||
943 | /* if($_charset != '' ) |
||||
944 | $_charset = "[$_charset] "; |
||||
945 | $param=sprintf("%s%s",$charset,$search_cmd); |
||||
946 | */ |
||||
947 | $ret = $this->_genericCommand('SEARCH', $search_cmd); |
||||
948 | if (isset($ret['PARSED'])) { |
||||
949 | $ret['PARSED'] = $ret['PARSED'][0]['EXT']; |
||||
950 | } |
||||
951 | |||||
952 | return $ret; |
||||
953 | } |
||||
954 | |||||
955 | /** |
||||
956 | * Send the STORE command. |
||||
957 | * |
||||
958 | * @param string $message_set the sessage_set |
||||
959 | * @param string $dataitem : the way we store the flags |
||||
960 | * FLAGS: replace the flags whith $value |
||||
961 | * FLAGS.SILENT: replace the flags whith $value but don't return untagged responses |
||||
962 | * |
||||
963 | * +FLAGS: Add the flags whith $value |
||||
964 | * +FLAGS.SILENT: Add the flags whith $value but don't return untagged responses |
||||
965 | * |
||||
966 | * -FLAGS: Remove the flags whith $value |
||||
967 | * -FLAGS.SILENT: Remove the flags whith $value but don't return untagged responses |
||||
968 | * |
||||
969 | * @param string $value |
||||
970 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
971 | * kind of failure, or true on success. |
||||
972 | * @since 1.0 |
||||
973 | */ |
||||
974 | public function cmdStore(string $message_set, string $dataitem, string $value) |
||||
975 | { |
||||
976 | /* As said in RFC2060... |
||||
977 | C: A003 STORE 2:4 +FLAGS (\Deleted) |
||||
978 | S: * 2 FETCH FLAGS (\Deleted \Seen) |
||||
979 | S: * 3 FETCH FLAGS (\Deleted) |
||||
980 | S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen) |
||||
981 | S: A003 OK STORE completed |
||||
982 | */ |
||||
983 | if ('FLAGS' !== $dataitem && 'FLAGS.SILENT' !== $dataitem && '+FLAGS' !== $dataitem |
||||
984 | && '+FLAGS.SILENT' !== $dataitem |
||||
985 | && '-FLAGS' !== $dataitem |
||||
986 | && '-FLAGS.SILENT' !== $dataitem) { |
||||
987 | $this->_prot_error("dataitem '$dataitem' is invalid! see RFC2060!!!!", __LINE__, __FILE__); |
||||
988 | } |
||||
989 | $param = sprintf('%s %s (%s)', $message_set, $dataitem, $value); |
||||
990 | |||||
991 | return $this->_genericCommand('STORE', $param); |
||||
992 | } |
||||
993 | |||||
994 | /** |
||||
995 | * Send the COPY command. |
||||
996 | * |
||||
997 | * @param string $message_set |
||||
998 | * @param string $mailbox |
||||
999 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1000 | * kind of failure, or true on success. |
||||
1001 | * @since 1.0 |
||||
1002 | */ |
||||
1003 | public function cmdCopy(string $message_set, string $mailbox) |
||||
1004 | { |
||||
1005 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
1006 | |||||
1007 | return $this->_genericCommand('COPY', sprintf('%s %s', $message_set, $mailbox_name)); |
||||
1008 | } |
||||
1009 | |||||
1010 | /** |
||||
1011 | * @param string $msgset |
||||
1012 | * @param string $fetchparam |
||||
1013 | * @return array|\PEAR_Error |
||||
1014 | */ |
||||
1015 | public function cmdUidFetch($msgset, $fetchparam) |
||||
1016 | { |
||||
1017 | return $this->_genericCommand('UID FETCH', sprintf('%s %s', $msgset, $fetchparam)); |
||||
1018 | } |
||||
1019 | |||||
1020 | /** |
||||
1021 | * @param string $message_set |
||||
1022 | * @param string $mailbox |
||||
1023 | * @return array|\PEAR_Error |
||||
1024 | */ |
||||
1025 | public function cmdUidCopy(string $message_set, string $mailbox) |
||||
1026 | { |
||||
1027 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox)); |
||||
1028 | |||||
1029 | return $this->_genericCommand('UID COPY', sprintf('%s %s', $message_set, $mailbox_name)); |
||||
1030 | } |
||||
1031 | |||||
1032 | /** |
||||
1033 | * Send the UID STORE command. |
||||
1034 | * |
||||
1035 | * @param string $message_set the sessage_set |
||||
1036 | * @param string $dataitem : the way we store the flags |
||||
1037 | * FLAGS: replace the flags whith $value |
||||
1038 | * FLAGS.SILENT: replace the flags whith $value but don't return untagged responses |
||||
1039 | * |
||||
1040 | * +FLAGS: Add the flags whith $value |
||||
1041 | * +FLAGS.SILENT: Add the flags whith $value but don't return untagged responses |
||||
1042 | * |
||||
1043 | * -FLAGS: Remove the flags whith $value |
||||
1044 | * -FLAGS.SILENT: Remove the flags whith $value but don't return untagged responses |
||||
1045 | * |
||||
1046 | * @param string $value |
||||
1047 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1048 | * kind of failure, or true on success. |
||||
1049 | * @since 1.0 |
||||
1050 | */ |
||||
1051 | public function cmdUidStore(string $message_set, string $dataitem, string $value) |
||||
1052 | { |
||||
1053 | /* As said in RFC2060... |
||||
1054 | C: A003 STORE 2:4 +FLAGS (\Deleted) |
||||
1055 | S: * 2 FETCH FLAGS (\Deleted \Seen) |
||||
1056 | S: * 3 FETCH FLAGS (\Deleted) |
||||
1057 | S: * 4 FETCH FLAGS (\Deleted \Flagged \Seen) |
||||
1058 | S: A003 OK STORE completed |
||||
1059 | */ |
||||
1060 | if ('FLAGS' !== $dataitem && 'FLAGS.SILENT' !== $dataitem && '+FLAGS' !== $dataitem |
||||
1061 | && '+FLAGS.SILENT' !== $dataitem |
||||
1062 | && '-FLAGS' !== $dataitem |
||||
1063 | && '-FLAGS.SILENT' !== $dataitem) { |
||||
1064 | $this->_prot_error("dataitem '$dataitem' is invalid! see RFC2060!!!!", __LINE__, __FILE__); |
||||
1065 | } |
||||
1066 | |||||
1067 | return $this->_genericCommand('UID STORE', sprintf('%s %s (%s)', $message_set, $dataitem, $value)); |
||||
1068 | } |
||||
1069 | |||||
1070 | /** |
||||
1071 | * Send the SEARCH command. |
||||
1072 | * |
||||
1073 | * @param string $search_cmd |
||||
1074 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1075 | * kind of failure, or true on success. |
||||
1076 | * @since 1.0 |
||||
1077 | */ |
||||
1078 | public function cmdUidSearch(string $search_cmd) |
||||
1079 | { |
||||
1080 | $ret = $this->_genericCommand('UID SEARCH', sprintf('%s', $search_cmd)); |
||||
1081 | if (isset($ret['PARSED'])) { |
||||
1082 | $ret['PARSED'] = $ret['PARSED'][0]['EXT']; |
||||
1083 | } |
||||
1084 | |||||
1085 | return $ret; |
||||
1086 | } |
||||
1087 | |||||
1088 | /** |
||||
1089 | * Send the X command. |
||||
1090 | * |
||||
1091 | * @param string $atom |
||||
1092 | * @param string $parameters |
||||
1093 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1094 | * kind of failure, or true on success. |
||||
1095 | * @since 1.0 |
||||
1096 | */ |
||||
1097 | public function cmdX($atom, $parameters) |
||||
1098 | { |
||||
1099 | return $this->_genericCommand("X$atom", $parameters); |
||||
1100 | } |
||||
1101 | |||||
1102 | /******************************************************************** |
||||
1103 | *** |
||||
1104 | *** HERE ENDS the RFC2060 IMAPS FUNCTIONS |
||||
1105 | *** AND BEGIN THE EXTENSIONS FUNCTIONS |
||||
1106 | *** |
||||
1107 | ********************************************************************/ |
||||
1108 | |||||
1109 | /******************************************************************** |
||||
1110 | *** RFC2087 IMAP4 QUOTA extension BEGINS HERE |
||||
1111 | ********************************************************************/ |
||||
1112 | |||||
1113 | /** |
||||
1114 | * Send the GETQUOTA command. |
||||
1115 | * |
||||
1116 | * @param string $mailbox_name the mailbox name to query for quota data |
||||
1117 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1118 | * kind of failure, or quota data on success |
||||
1119 | * @since 1.0 |
||||
1120 | */ |
||||
1121 | public function cmdGetQuota(string $mailbox_name) |
||||
1122 | { |
||||
1123 | //Check if the IMAP server has QUOTA support |
||||
1124 | if (!$this->hasQuotaSupport()) { |
||||
1125 | return new PEAR_Error("This IMAP server does not support QUOTA's! "); |
||||
1126 | } |
||||
1127 | $mailbox_name = sprintf('%s', $this->utf_7_encode($mailbox_name)); |
||||
1128 | $ret = $this->_genericCommand('GETQUOTA', $mailbox_name); |
||||
1129 | if (isset($ret['PARSED'])) { |
||||
1130 | // remove the array index because the quota response returns only 1 line of output |
||||
1131 | $ret['PARSED'] = $ret['PARSED'][0]; |
||||
1132 | } |
||||
1133 | |||||
1134 | return $ret; |
||||
1135 | } |
||||
1136 | |||||
1137 | /** |
||||
1138 | * Send the GETQUOTAROOT command. |
||||
1139 | * |
||||
1140 | * @param string $mailbox_name the mailbox name to query for quota data |
||||
1141 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1142 | * kind of failure, or quota data on success |
||||
1143 | * @since 1.0 |
||||
1144 | */ |
||||
1145 | public function cmdGetQuotaRoot(string $mailbox_name) |
||||
1146 | { |
||||
1147 | //Check if the IMAP server has QUOTA support |
||||
1148 | if (!$this->hasQuotaSupport()) { |
||||
1149 | return new PEAR_Error("This IMAP server does not support QUOTA's! "); |
||||
1150 | } |
||||
1151 | $mailbox_name = sprintf('%s', $this->utf_7_encode($mailbox_name)); |
||||
1152 | $ret = $this->_genericCommand('GETQUOTAROOT', $mailbox_name); |
||||
1153 | |||||
1154 | if (isset($ret['PARSED'])) { |
||||
1155 | // remove the array index because the quota response returns only 1 line of output |
||||
1156 | $ret['PARSED'] = $ret['PARSED'][0]; |
||||
1157 | } |
||||
1158 | |||||
1159 | return $ret; |
||||
1160 | } |
||||
1161 | |||||
1162 | /** |
||||
1163 | * Send the SETQUOTA command. |
||||
1164 | * |
||||
1165 | * @param string $mailbox_name the mailbox name to query for quota data |
||||
1166 | * @param int|null $storageQuota sets the max number of bytes this mailbox can handle |
||||
1167 | * @param int|null $messagesQuota sets the max number of messages this mailbox can handle |
||||
1168 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1169 | * kind of failure, or quota data on success |
||||
1170 | * @since 1.0 |
||||
1171 | */ |
||||
1172 | // TODO: implement the quota by number of emails!! |
||||
1173 | public function cmdSetQuota(string $mailbox_name, int $storageQuota = null, int $messagesQuota = null) |
||||
1174 | { |
||||
1175 | //Check if the IMAP server has QUOTA support |
||||
1176 | if (!$this->hasQuotaSupport()) { |
||||
1177 | return new PEAR_Error("This IMAP server does not support QUOTA's! "); |
||||
1178 | } |
||||
1179 | |||||
1180 | if ((null === $messagesQuota) && (null === $storageQuota)) { |
||||
1181 | return new PEAR_Error('$storageQuota and $messagesQuota parameters can\'t be both null if you want to use quota'); |
||||
1182 | } |
||||
1183 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox_name)); |
||||
1184 | //Make the command request |
||||
1185 | $param = sprintf('%s (', $mailbox_name); |
||||
1186 | if (null !== $storageQuota) { |
||||
1187 | $param = sprintf('%sSTORAGE %s', $param, $storageQuota); |
||||
1188 | if (null !== $messagesQuota) { |
||||
1189 | //if we have both types of quota on the same call we must append an space between |
||||
1190 | // those parameters |
||||
1191 | $param = sprintf('%s ', $param); |
||||
1192 | } |
||||
1193 | } |
||||
1194 | if (null !== $messagesQuota) { |
||||
1195 | $param = sprintf('%sMESSAGES %s', $param, $messagesQuota); |
||||
1196 | } |
||||
1197 | $param = sprintf('%s)', $param); |
||||
1198 | |||||
1199 | return $this->_genericCommand('SETQUOTA', $param); |
||||
1200 | } |
||||
1201 | |||||
1202 | /** |
||||
1203 | * Send the SETQUOTAROOT command. |
||||
1204 | * |
||||
1205 | * @param string $mailbox_name the mailbox name to query for quota data |
||||
1206 | * @param null $storageQuota sets the max number of bytes this mailbox can handle |
||||
0 ignored issues
–
show
|
|||||
1207 | * @param null $messagesQuota sets the max number of messages this mailbox can handle |
||||
0 ignored issues
–
show
|
|||||
1208 | * @return array|\PEAR_Error Returns a PEAR_Error with an error message on any |
||||
1209 | * kind of failure, or quota data on success |
||||
1210 | * @since 1.0 |
||||
1211 | */ |
||||
1212 | public function cmdSetQuotaRoot(string $mailbox_name, $storageQuota = null, $messagesQuota = null) |
||||
1213 | { |
||||
1214 | //Check if the IMAP server has QUOTA support |
||||
1215 | if (!$this->hasQuotaSupport()) { |
||||
1216 | return new PEAR_Error("This IMAP server does not support QUOTA's! "); |
||||
1217 | } |
||||
1218 | |||||
1219 | if ((null === $messagesQuota) && (null === $storageQuota)) { |
||||
0 ignored issues
–
show
|
|||||
1220 | return new PEAR_Error('$storageQuota and $messagesQuota parameters can\'t be both null if you want to use quota'); |
||||
1221 | } |
||||
1222 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox_name)); |
||||
1223 | //Make the command request |
||||
1224 | $param = sprintf('%s (', $mailbox_name); |
||||
1225 | if (null !== $storageQuota) { |
||||
1226 | $param = sprintf('%sSTORAGE %s', $param, $storageQuota); |
||||
1227 | if (null !== $messagesQuota) { |
||||
1228 | //if we have both types of quota on the same call we must append an space between |
||||
1229 | // those parameters |
||||
1230 | $param = sprintf('%s ', $param); |
||||
1231 | } |
||||
1232 | } |
||||
1233 | if (null !== $messagesQuota) { |
||||
1234 | $param = sprintf('%sMESSAGES %s', $param, $messagesQuota); |
||||
1235 | } |
||||
1236 | $param = sprintf('%s)', $param); |
||||
1237 | |||||
1238 | return $this->_genericCommand('SETQUOTAROOT', $param); |
||||
1239 | } |
||||
1240 | |||||
1241 | /******************************************************************** |
||||
1242 | *** RFC2087 IMAP4 QUOTA extension ENDS HERE |
||||
1243 | ********************************************************************/ |
||||
1244 | |||||
1245 | /******************************************************************** |
||||
1246 | *** RFC2086 IMAP4 ACL extension BEGINS HERE |
||||
1247 | ******************************************************************* |
||||
1248 | * @param string $mailbox_name |
||||
1249 | * @param string $user |
||||
1250 | * @param array|string $acl |
||||
1251 | * @return array|\PEAR_Error |
||||
1252 | */ |
||||
1253 | |||||
1254 | public function cmdSetACL(string $mailbox_name, string $user, $acl) |
||||
1255 | { |
||||
1256 | //Check if the IMAP server has ACL support |
||||
1257 | if (!$this->hasAclSupport()) { |
||||
1258 | return new PEAR_Error("This IMAP server does not support ACL's! "); |
||||
1259 | } |
||||
1260 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox_name)); |
||||
1261 | $user_name = sprintf('"%s"', $this->utf_7_encode($user)); |
||||
1262 | if (is_array($acl)) { |
||||
1263 | $acl = implode('', $acl); |
||||
1264 | } |
||||
1265 | |||||
1266 | return $this->_genericCommand('SETACL', sprintf('%s %s "%s"', $mailbox_name, $user_name, $acl)); |
||||
1267 | } |
||||
1268 | |||||
1269 | /** |
||||
1270 | * @param string $mailbox_name |
||||
1271 | * @param string $user |
||||
1272 | * @return array|\PEAR_Error |
||||
1273 | */ |
||||
1274 | public function cmdDeleteACL(string $mailbox_name, string $user) |
||||
1275 | { |
||||
1276 | //Check if the IMAP server has ACL support |
||||
1277 | if (!$this->hasAclSupport()) { |
||||
1278 | return new PEAR_Error("This IMAP server does not support ACL's! "); |
||||
1279 | } |
||||
1280 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox_name)); |
||||
1281 | |||||
1282 | return $this->_genericCommand('DELETEACL', sprintf('%s "%s"', $mailbox_name, $user)); |
||||
1283 | } |
||||
1284 | |||||
1285 | /** |
||||
1286 | * @param string $mailbox_name |
||||
1287 | * @return array|\PEAR_Error |
||||
1288 | */ |
||||
1289 | public function cmdGetACL(string $mailbox_name) |
||||
1290 | { |
||||
1291 | //Check if the IMAP server has ACL support |
||||
1292 | if (!$this->hasAclSupport()) { |
||||
1293 | return new PEAR_Error("This IMAP server does not support ACL's! "); |
||||
1294 | } |
||||
1295 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox_name)); |
||||
1296 | $ret = $this->_genericCommand('GETACL', sprintf('%s', $mailbox_name)); |
||||
1297 | if (isset($ret['PARSED'])) { |
||||
1298 | $ret['PARSED'] = $ret['PARSED'][0]['EXT']; |
||||
1299 | } |
||||
1300 | |||||
1301 | return $ret; |
||||
1302 | } |
||||
1303 | |||||
1304 | /** |
||||
1305 | * @param string $mailbox_name |
||||
1306 | * @param string $user |
||||
1307 | * @return array|\PEAR_Error |
||||
1308 | */ |
||||
1309 | public function cmdListRights(string $mailbox_name, string $user) |
||||
1310 | { |
||||
1311 | //Check if the IMAP server has ACL support |
||||
1312 | if (!$this->hasAclSupport()) { |
||||
1313 | return new PEAR_Error("This IMAP server does not support ACL's! "); |
||||
1314 | } |
||||
1315 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox_name)); |
||||
1316 | $ret = $this->_genericCommand('LISTRIGHTS', sprintf('%s "%s"', $mailbox_name, $user)); |
||||
1317 | if (isset($ret['PARSED'])) { |
||||
1318 | $ret['PARSED'] = $ret['PARSED'][0]['EXT']; |
||||
1319 | } |
||||
1320 | |||||
1321 | return $ret; |
||||
1322 | } |
||||
1323 | |||||
1324 | /** |
||||
1325 | * @param string $mailbox_name |
||||
1326 | * @return array|\PEAR_Error |
||||
1327 | */ |
||||
1328 | public function cmdMyRights(string $mailbox_name) |
||||
1329 | { |
||||
1330 | //Check if the IMAP server has ACL support |
||||
1331 | if (!$this->hasAclSupport()) { |
||||
1332 | return new PEAR_Error("This IMAP server does not support ACL's! "); |
||||
1333 | } |
||||
1334 | $mailbox_name = sprintf('"%s"', $this->utf_7_encode($mailbox_name)); |
||||
1335 | $ret = $this->_genericCommand('MYRIGHTS', sprintf('%s', $mailbox_name)); |
||||
1336 | if (isset($ret['PARSED'])) { |
||||
1337 | $ret['PARSED'] = $ret['PARSED'][0]['EXT']; |
||||
1338 | } |
||||
1339 | |||||
1340 | return $ret; |
||||
1341 | } |
||||
1342 | |||||
1343 | /******************************************************************** |
||||
1344 | *** RFC2086 IMAP4 ACL extension ENDs HERE |
||||
1345 | ********************************************************************/ |
||||
1346 | |||||
1347 | /******************************************************************************* |
||||
1348 | *** draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension BEGINS HERE |
||||
1349 | ******************************************************************************* |
||||
1350 | * @param string $mailbox_name |
||||
1351 | * @param string $entry |
||||
1352 | * @param array $values |
||||
1353 | * @return array|\PEAR_Error |
||||
1354 | */ |
||||
1355 | |||||
1356 | public function cmdSetAnnotation(string $mailbox_name, string $entry, array $values) |
||||
1357 | { |
||||
1358 | // Check if the IMAP server has ANNOTATEMORE support |
||||
1359 | if (!$this->hasAnnotateMoreSupport()) { |
||||
1360 | return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!'); |
||||
1361 | } |
||||
1362 | if (!is_array($values)) { |
||||
0 ignored issues
–
show
|
|||||
1363 | return new PEAR_Error('Invalid $values argument passed to cmdSetAnnotation'); |
||||
1364 | } |
||||
1365 | |||||
1366 | $vallist = ''; |
||||
1367 | foreach ($values as $name => $value) { |
||||
1368 | $vallist .= "\"$name\" \"$value\" "; |
||||
1369 | } |
||||
1370 | $vallist = rtrim($vallist); |
||||
1371 | |||||
1372 | return $this->_genericCommand('SETANNOTATION', sprintf('"%s" "%s" (%s)', $mailbox_name, $entry, $vallist)); |
||||
1373 | } |
||||
1374 | |||||
1375 | /** |
||||
1376 | * @param string $mailbox_name |
||||
1377 | * @param string $entry |
||||
1378 | * @param array $values |
||||
1379 | * @return array|\PEAR_Error |
||||
1380 | */ |
||||
1381 | public function cmdDeleteAnnotation(string $mailbox_name, string $entry, array $values) |
||||
1382 | { |
||||
1383 | // Check if the IMAP server has ANNOTATEMORE support |
||||
1384 | if (!$this->hasAnnotateMoreSupport()) { |
||||
1385 | return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!'); |
||||
1386 | } |
||||
1387 | if (!is_array($values)) { |
||||
0 ignored issues
–
show
|
|||||
1388 | return new PEAR_Error('Invalid $values argument passed to cmdDeleteAnnotation'); |
||||
1389 | } |
||||
1390 | |||||
1391 | $vallist = ''; |
||||
1392 | foreach ($values as $name) { |
||||
1393 | $vallist .= "\"$name\" NIL "; |
||||
1394 | } |
||||
1395 | $vallist = rtrim($vallist); |
||||
1396 | |||||
1397 | return $this->_genericCommand('SETANNOTATION', sprintf('"%s" "%s" (%s)', $mailbox_name, $entry, $vallist)); |
||||
1398 | } |
||||
1399 | |||||
1400 | /** |
||||
1401 | * @param string $mailbox_name |
||||
1402 | * @param array $entries |
||||
1403 | * @param array $values |
||||
1404 | * @return array|\PEAR_Error |
||||
1405 | */ |
||||
1406 | public function cmdGetAnnotation(string $mailbox_name, array $entries, array $values) |
||||
1407 | { |
||||
1408 | // Check if the IMAP server has ANNOTATEMORE support |
||||
1409 | if (!$this->hasAnnotateMoreSupport()) { |
||||
1410 | return new PEAR_Error('This IMAP server does not support the ANNOTATEMORE extension!'); |
||||
1411 | } |
||||
1412 | |||||
1413 | $entlist = ''; |
||||
1414 | |||||
1415 | if (!is_array($entries)) { |
||||
0 ignored issues
–
show
|
|||||
1416 | $entries = [$entries]; |
||||
1417 | } |
||||
1418 | |||||
1419 | foreach ($entries as $name) { |
||||
1420 | $entlist .= "\"$name\" "; |
||||
1421 | } |
||||
1422 | $entlist = rtrim($entlist); |
||||
1423 | if (count($entries) > 1) { |
||||
1424 | $entlist = "($entlist)"; |
||||
1425 | } |
||||
1426 | |||||
1427 | $vallist = ''; |
||||
1428 | if (!is_array($values)) { |
||||
0 ignored issues
–
show
|
|||||
1429 | $values = [$values]; |
||||
1430 | } |
||||
1431 | |||||
1432 | foreach ($values as $name) { |
||||
1433 | $vallist .= "\"$name\" "; |
||||
1434 | } |
||||
1435 | $vallist = rtrim($vallist); |
||||
1436 | if (count($values) > 1) { |
||||
1437 | $vallist = "($vallist)"; |
||||
1438 | } |
||||
1439 | |||||
1440 | return $this->_genericCommand('GETANNOTATION', sprintf('"%s" %s %s', $mailbox_name, $entlist, $vallist)); |
||||
1441 | } |
||||
1442 | |||||
1443 | /***************************************************************************** |
||||
1444 | *** draft-daboo-imap-annotatemore-05 IMAP4 ANNOTATEMORE extension ENDs HERE |
||||
1445 | ******************************************************************************/ |
||||
1446 | |||||
1447 | /******************************************************************** |
||||
1448 | *** |
||||
1449 | *** HERE ENDS THE EXTENSIONS FUNCTIONS |
||||
1450 | *** AND BEGIN THE AUXILIARY FUNCTIONS |
||||
1451 | *** |
||||
1452 | ********************************************************************/ |
||||
1453 | |||||
1454 | /** |
||||
1455 | * tell if the server has capability $capability |
||||
1456 | * |
||||
1457 | * @return true or false |
||||
1458 | * |
||||
1459 | * @since 1.0 |
||||
1460 | */ |
||||
1461 | public function getServerAuthMethods(): ?bool |
||||
1462 | { |
||||
1463 | if (null === $this->_serverAuthMethods) { |
||||
1464 | $this->cmdCapability(); |
||||
1465 | |||||
1466 | return $this->_serverAuthMethods; |
||||
0 ignored issues
–
show
|
|||||
1467 | } |
||||
1468 | |||||
1469 | return false; |
||||
0 ignored issues
–
show
|
|||||
1470 | } |
||||
1471 | |||||
1472 | /** |
||||
1473 | * tell if the server has capability $capability |
||||
1474 | * |
||||
1475 | * @param string $capability |
||||
1476 | * @return true or false |
||||
1477 | * |
||||
1478 | * @since 1.0 |
||||
1479 | */ |
||||
1480 | public function hasCapability(string $capability): bool |
||||
1481 | { |
||||
1482 | if (null === $this->_serverSupportedCapabilities) { |
||||
1483 | $this->cmdCapability(); |
||||
1484 | } |
||||
1485 | if (null !== $this->_serverSupportedCapabilities) { |
||||
1486 | if (in_array($capability, $this->_serverSupportedCapabilities, true)) { |
||||
1487 | return true; |
||||
1488 | } |
||||
1489 | } |
||||
1490 | |||||
1491 | return false; |
||||
0 ignored issues
–
show
|
|||||
1492 | } |
||||
1493 | |||||
1494 | /** |
||||
1495 | * tell if the server has Quota support |
||||
1496 | * |
||||
1497 | * @return true or false |
||||
1498 | * |
||||
1499 | * @since 1.0 |
||||
1500 | */ |
||||
1501 | public function hasQuotaSupport(): bool |
||||
1502 | { |
||||
1503 | return $this->hasCapability('QUOTA'); |
||||
0 ignored issues
–
show
|
|||||
1504 | } |
||||
1505 | |||||
1506 | /** |
||||
1507 | * tell if the server has Quota support |
||||
1508 | * |
||||
1509 | * @return true or false |
||||
1510 | * |
||||
1511 | * @since 1.0 |
||||
1512 | */ |
||||
1513 | public function hasAclSupport(): bool |
||||
1514 | { |
||||
1515 | return $this->hasCapability('ACL'); |
||||
0 ignored issues
–
show
|
|||||
1516 | } |
||||
1517 | |||||
1518 | /** |
||||
1519 | * tell if the server has support for the ANNOTATEMORE extension |
||||
1520 | * |
||||
1521 | * @return true or false |
||||
1522 | * |
||||
1523 | * @since 1.0 |
||||
1524 | */ |
||||
1525 | public function hasAnnotateMoreSupport(): bool |
||||
1526 | { |
||||
1527 | return $this->hasCapability('ANNOTATEMORE'); |
||||
0 ignored issues
–
show
|
|||||
1528 | } |
||||
1529 | |||||
1530 | /** |
||||
1531 | * Parses the responses like RFC822.SIZE and INTERNALDATE |
||||
1532 | * |
||||
1533 | * @param string $str |
||||
1534 | * @param string $line |
||||
1535 | * @param string $file |
||||
1536 | * @return string containing the parsed response |
||||
1537 | * @since 1.0 |
||||
1538 | */ |
||||
1539 | public function _parseOneStringResponse(&$str, $line, $file): string |
||||
1540 | { |
||||
1541 | $this->_parseSpace($str, $line, $file); |
||||
1542 | $size = $this->_getNextToken($str, $uid); |
||||
0 ignored issues
–
show
|
|||||
1543 | |||||
1544 | return $uid; |
||||
1545 | } |
||||
1546 | |||||
1547 | /** |
||||
1548 | * Parses the FLAG response |
||||
1549 | * |
||||
1550 | * @param mixed $str |
||||
1551 | * |
||||
1552 | * @return array containing the parsed response |
||||
1553 | * @since 1.0 |
||||
1554 | */ |
||||
1555 | public function _parseFLAGSresponse(&$str): array |
||||
1556 | { |
||||
1557 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1558 | $params_arr[] = $this->_arrayfy_content($str); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
1559 | $flags_arr = []; |
||||
1560 | foreach ($params_arr[0] as $iValue) { |
||||
1561 | $flags_arr[] = $iValue; |
||||
1562 | } |
||||
1563 | |||||
1564 | return $flags_arr; |
||||
1565 | } |
||||
1566 | |||||
1567 | /** |
||||
1568 | * Parses the BODY response |
||||
1569 | * |
||||
1570 | * @param string $str |
||||
1571 | * @param string $command |
||||
1572 | * @return array containing the parsed response |
||||
1573 | * @since 1.0 |
||||
1574 | */ |
||||
1575 | public function _parseBodyResponse(&$str, $command): array |
||||
0 ignored issues
–
show
The parameter
$command is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
1576 | { |
||||
1577 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1578 | while (')' !== $str[0] && '' != $str) { |
||||
1579 | $params_arr[] = $this->_arrayfy_content($str); |
||||
1580 | } |
||||
1581 | |||||
1582 | return $params_arr; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
1583 | } |
||||
1584 | |||||
1585 | /** |
||||
1586 | * Makes the content an Array |
||||
1587 | * |
||||
1588 | * @param mixed $str |
||||
1589 | * |
||||
1590 | * @return array containing the parsed response |
||||
1591 | * @since 1.0 |
||||
1592 | */ |
||||
1593 | public function _arrayfy_content(&$str): array |
||||
1594 | { |
||||
1595 | $params_arr = []; |
||||
1596 | $this->_getNextToken($str, $params); |
||||
1597 | if ('(' !== $params) { |
||||
1598 | return $params; |
||||
1599 | } |
||||
1600 | $this->_getNextToken($str, $params, false, false); |
||||
1601 | while ('' != $str && ')' !== $params) { |
||||
1602 | if ('' != $params) { |
||||
1603 | if ('(' === $params[0]) { |
||||
1604 | $params = $this->_arrayfy_content($params); |
||||
1605 | } |
||||
1606 | if (' ' !== $params) { |
||||
1607 | //I don't remove the colons (") to handle the case of retriving " " |
||||
1608 | // If I remove the colons the parser will interpret this field as an imap separator (space) |
||||
1609 | // instead of a valid field so I remove the colons here |
||||
1610 | if ('""' === $params) { |
||||
1611 | $params = ''; |
||||
1612 | } else { |
||||
1613 | if ('"' === $params[0]) { |
||||
1614 | $params = mb_substr($params, 1, -2); |
||||
1615 | } |
||||
1616 | } |
||||
1617 | $params_arr[] = $params; |
||||
1618 | } |
||||
1619 | } else { |
||||
1620 | //if params if empty (for example i'm parsing 2 quotes ("") |
||||
1621 | // I'll append an array entry to mantain compatibility |
||||
1622 | $params_arr[] = $params; |
||||
1623 | } |
||||
1624 | $this->_getNextToken($str, $params, false, false); |
||||
1625 | } |
||||
1626 | |||||
1627 | return $params_arr; |
||||
1628 | } |
||||
1629 | |||||
1630 | /** |
||||
1631 | * Parses the BODY[],BODY[TEXT],.... responses |
||||
1632 | * |
||||
1633 | * @param string $str |
||||
1634 | * @param string $command |
||||
1635 | * @return array containing the parsed response |
||||
1636 | * @since 1.0 |
||||
1637 | */ |
||||
1638 | public function _parseContentresponse(&$str, $command): array |
||||
0 ignored issues
–
show
The parameter
$command is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
1639 | { |
||||
1640 | $content = ''; |
||||
1641 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1642 | $size = $this->_getNextToken($str, $content); |
||||
1643 | |||||
1644 | return ['CONTENT' => $content, 'CONTENT_SIZE' => $size]; |
||||
1645 | } |
||||
1646 | |||||
1647 | /** |
||||
1648 | * Parses the ENVELOPE response |
||||
1649 | * |
||||
1650 | * @param mixed $str |
||||
1651 | * |
||||
1652 | * @return array containing the parsed response |
||||
1653 | * @since 1.0 |
||||
1654 | */ |
||||
1655 | public function _parseENVELOPEresponse(&$str): array |
||||
1656 | { |
||||
1657 | $content = ''; |
||||
0 ignored issues
–
show
|
|||||
1658 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1659 | |||||
1660 | $this->_getNextToken($str, $parenthesis); |
||||
1661 | if ('(' !== $parenthesis) { |
||||
1662 | $this->_prot_error("must be a '(' but is a '$parenthesis' !!!!", __LINE__, __FILE__); |
||||
1663 | } |
||||
1664 | // Get the email's Date |
||||
1665 | $this->_getNextToken($str, $date); |
||||
1666 | |||||
1667 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1668 | |||||
1669 | // Get the email's Subject: |
||||
1670 | $this->_getNextToken($str, $subject); |
||||
1671 | //$subject=$this->decode($subject); |
||||
1672 | |||||
1673 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1674 | |||||
1675 | //FROM LIST; |
||||
1676 | $from_arr = $this->_getAddressList($str); |
||||
1677 | |||||
1678 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1679 | |||||
1680 | //"SENDER LIST\n"; |
||||
1681 | $sender_arr = $this->_getAddressList($str); |
||||
1682 | |||||
1683 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1684 | |||||
1685 | //"REPLY-TO LIST\n"; |
||||
1686 | $reply_to_arr = $this->_getAddressList($str); |
||||
1687 | |||||
1688 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1689 | |||||
1690 | //"TO LIST\n"; |
||||
1691 | $to_arr = $this->_getAddressList($str); |
||||
1692 | |||||
1693 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1694 | |||||
1695 | //"CC LIST\n"; |
||||
1696 | $cc_arr = $this->_getAddressList($str); |
||||
1697 | |||||
1698 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1699 | |||||
1700 | //"BCC LIST|$str|\n"; |
||||
1701 | $bcc_arr = $this->_getAddressList($str); |
||||
1702 | |||||
1703 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1704 | |||||
1705 | $this->_getNextToken($str, $in_reply_to); |
||||
1706 | |||||
1707 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
1708 | |||||
1709 | $this->_getNextToken($str, $message_id); |
||||
1710 | |||||
1711 | $this->_getNextToken($str, $parenthesis); |
||||
1712 | |||||
1713 | if (')' !== $parenthesis) { |
||||
1714 | $this->_prot_error("must be a ')' but is a '$parenthesis' !!!!", __LINE__, __FILE__); |
||||
1715 | } |
||||
1716 | |||||
1717 | return [ |
||||
1718 | 'DATE' => $date, |
||||
1719 | 'SUBJECT' => $subject, |
||||
1720 | 'FROM' => $from_arr, |
||||
1721 | 'SENDER' => $sender_arr, |
||||
1722 | 'REPLY_TO' => $reply_to_arr, |
||||
1723 | 'TO' => $to_arr, |
||||
1724 | 'CC' => $cc_arr, |
||||
1725 | 'BCC' => $bcc_arr, |
||||
1726 | 'IN_REPLY_TO' => $in_reply_to, |
||||
1727 | 'MESSAGE_ID' => $message_id, |
||||
1728 | ]; |
||||
1729 | } |
||||
1730 | |||||
1731 | /** |
||||
1732 | * Parses the ARRDLIST as defined in RFC |
||||
1733 | * |
||||
1734 | * @param mixed $str |
||||
1735 | * |
||||
1736 | * @return array containing the parsed response |
||||
1737 | * @since 1.0 |
||||
1738 | */ |
||||
1739 | public function _getAddressList(&$str): array |
||||
1740 | { |
||||
1741 | $params_arr = $this->_arrayfy_content($str); |
||||
1742 | if (!isset($params_arr)) { |
||||
1743 | return $params_arr; |
||||
1744 | } |
||||
1745 | |||||
1746 | if (is_array($params_arr)) { |
||||
0 ignored issues
–
show
|
|||||
1747 | $personal_name = $params_arr[0][0]; |
||||
1748 | $at_domain_list = $params_arr[0][1]; |
||||
1749 | $mailbox_name = $params_arr[0][2]; |
||||
1750 | $host_name = $params_arr[0][3]; |
||||
1751 | if ('' != $mailbox_name && '' != $host_name) { |
||||
1752 | $email = $mailbox_name . '@' . $host_name; |
||||
1753 | } else { |
||||
1754 | $email = false; |
||||
1755 | } |
||||
1756 | if (false !== $email) { |
||||
1757 | if (isset($personal_name)) { |
||||
1758 | $rfc822_email = '"' . $personal_name . '" <' . $email . '>'; |
||||
1759 | } else { |
||||
1760 | $rfc822_email = '<' . $email . '>'; |
||||
1761 | } |
||||
1762 | } else { |
||||
1763 | $rfc822_email = false; |
||||
1764 | } |
||||
1765 | $email_arr[] = [ |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
1766 | 'PERSONAL_NAME' => $personal_name, |
||||
1767 | 'AT_DOMAIN_LIST' => $at_domain_list, |
||||
1768 | 'MAILBOX_NAME' => $this->utf_7_decode($mailbox_name), |
||||
1769 | 'HOST_NAME' => $host_name, |
||||
1770 | 'EMAIL' => $email, |
||||
1771 | 'RFC822_EMAIL' => $rfc822_email, |
||||
1772 | ]; |
||||
1773 | |||||
1774 | return $email_arr; |
||||
1775 | } |
||||
1776 | |||||
1777 | return []; |
||||
1778 | } |
||||
1779 | |||||
1780 | /** |
||||
1781 | * Utility funcion to find the closing parenthesis ")" Position it takes care of quoted ones |
||||
1782 | * |
||||
1783 | * @param $str_line |
||||
1784 | * @param string $startDelim |
||||
1785 | * @param string $stopDelim |
||||
1786 | * @return int containing the pos of the closing parenthesis ")" |
||||
1787 | * @since 1.0 |
||||
1788 | */ |
||||
1789 | public function _getClosingBracesPos($str_line, string $startDelim = '(', string $stopDelim = ')') |
||||
1790 | { |
||||
1791 | $len = mb_strlen($str_line); |
||||
1792 | $pos = 0; |
||||
1793 | // ignore all extra characters |
||||
1794 | // If inside of a string, skip string -- Boundary IDs and other |
||||
1795 | // things can have ) in them. |
||||
1796 | if ($str_line[$pos] != $startDelim) { |
||||
1797 | $this->_prot_error("_getClosingParenthesisPos: must start with a '(' but is a '" . $str_line[$pos] . "'!!!!\n" . "STR_LINE:$str_line|size:$len|POS: $pos\n", __LINE__, __FILE__); |
||||
1798 | |||||
1799 | return $len; |
||||
1800 | } |
||||
1801 | for ($pos = 1; $pos < $len; $pos++) { |
||||
1802 | if ($str_line[$pos] == $stopDelim) { |
||||
1803 | break; |
||||
1804 | } |
||||
1805 | if ('"' === $str_line[$pos]) { |
||||
1806 | $pos++; |
||||
1807 | while ('"' !== $str_line[$pos] && $pos < $len) { |
||||
1808 | if ('\\' === $str_line[$pos] && '"' === $str_line[$pos + 1]) { |
||||
1809 | $pos++; |
||||
1810 | } |
||||
1811 | if ('\\' === $str_line[$pos] && '\\' === $str_line[$pos + 1]) { |
||||
1812 | $pos++; |
||||
1813 | } |
||||
1814 | $pos++; |
||||
1815 | } |
||||
1816 | } |
||||
1817 | if ($str_line[$pos] == $startDelim) { |
||||
1818 | $str_line_aux = mb_substr($str_line, $pos); |
||||
1819 | $pos_aux = $this->_getClosingBracesPos($str_line_aux); |
||||
1820 | $pos += $pos_aux; |
||||
1821 | } |
||||
1822 | } |
||||
1823 | if ($str_line[$pos] != $stopDelim) { |
||||
1824 | $this->_prot_error("_getClosingBracesPos: must be a $stopDelim but is a '" . $str_line[$pos] . "'|POS:$pos|STR_LINE:$str_line!!!!", __LINE__, __FILE__); |
||||
1825 | } |
||||
1826 | |||||
1827 | if ($pos >= $len) { |
||||
1828 | return false; |
||||
0 ignored issues
–
show
|
|||||
1829 | } |
||||
1830 | |||||
1831 | return $pos; |
||||
1832 | } |
||||
1833 | |||||
1834 | /** |
||||
1835 | * Utility funcion to get from here to the end of the line |
||||
1836 | * |
||||
1837 | * @param mixed $str |
||||
1838 | * @param bool $including |
||||
1839 | * @return string containing the string to the end of the line |
||||
1840 | * @since 1.0 |
||||
1841 | */ |
||||
1842 | public function _getToEOL(&$str, bool $including = true): string |
||||
1843 | { |
||||
1844 | $len = mb_strlen($str); |
||||
1845 | if ($including) { |
||||
1846 | for ($i = 0; $i < $len; ++$i) { |
||||
1847 | if ("\n" === $str[$i]) { |
||||
1848 | break; |
||||
1849 | } |
||||
1850 | } |
||||
1851 | $content = mb_substr($str, 0, $i + 1); |
||||
1852 | $str = mb_substr($str, $i + 1); |
||||
1853 | |||||
1854 | return $content; |
||||
1855 | } |
||||
1856 | for ($i = 0; $i < $len; ++$i) { |
||||
1857 | if ("\n" === $str[$i] || "\r" === $str[$i]) { |
||||
1858 | break; |
||||
1859 | } |
||||
1860 | } |
||||
1861 | $content = mb_substr($str, 0, $i); |
||||
1862 | $str = mb_substr($str, $i); |
||||
1863 | |||||
1864 | return $content; |
||||
1865 | } |
||||
1866 | |||||
1867 | /** |
||||
1868 | * Fetches the next IMAP token or parenthesis |
||||
1869 | * |
||||
1870 | * @param bool $parenthesisIsToken |
||||
1871 | * @param bool $colonIsToken |
||||
1872 | * @param mixed $str |
||||
1873 | * @param mixed $content |
||||
1874 | * @return int containing the content size |
||||
1875 | * @since 1.0 |
||||
1876 | */ |
||||
1877 | public function _getNextToken(&$str, &$content, bool $parenthesisIsToken = true, bool $colonIsToken = true) |
||||
1878 | { |
||||
1879 | $len = mb_strlen($str); |
||||
1880 | $pos = 0; |
||||
1881 | $content_size = false; |
||||
1882 | $content = false; |
||||
1883 | if ('' === $str || $len < 2) { |
||||
1884 | $content = $str; |
||||
1885 | |||||
1886 | return $len; |
||||
1887 | } |
||||
1888 | switch ($str[0]) { |
||||
1889 | case '{': |
||||
1890 | if (false === ($posClosingBraces = $this->_getClosingBracesPos($str, '{', '}'))) { |
||||
0 ignored issues
–
show
|
|||||
1891 | $this->_prot_error('_getClosingBracesPos() error!!!', __LINE__, __FILE__); |
||||
1892 | } |
||||
1893 | if (!is_numeric($strBytes = mb_substr($str, 1, $posClosingBraces - 1))) { |
||||
1894 | $this->_prot_error("must be a number but is a '" . $strBytes . "'!!!!", __LINE__, __FILE__); |
||||
1895 | } |
||||
1896 | if ('}' !== $str[$posClosingBraces]) { |
||||
1897 | $this->_prot_error("must be a '}' but is a '" . $str[$posClosingBraces] . "'!!!!", __LINE__, __FILE__); |
||||
1898 | } |
||||
1899 | if ("\r" !== $str[$posClosingBraces + 1]) { |
||||
1900 | $this->_prot_error("must be a '\\r' but is a '" . $str[$posClosingBraces + 1] . "'!!!!", __LINE__, __FILE__); |
||||
1901 | } |
||||
1902 | if ("\n" !== $str[$posClosingBraces + 2]) { |
||||
1903 | $this->_prot_error("must be a '\\n' but is a '" . $str[$posClosingBraces + 2] . "'!!!!", __LINE__, __FILE__); |
||||
1904 | } |
||||
1905 | $content = mb_substr($str, $posClosingBraces + 3, $strBytes); |
||||
0 ignored issues
–
show
$strBytes of type string is incompatible with the type integer|null expected by parameter $length of mb_substr() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
1906 | if (mb_strlen($content) != $strBytes) { |
||||
1907 | $this->_prot_error('content size is ' . mb_strlen($content) . " but the string reports a size of $strBytes!!!\n", __LINE__, __FILE__); |
||||
1908 | } |
||||
1909 | $content_size = $strBytes; |
||||
1910 | //Advance the string |
||||
1911 | $str = mb_substr($str, $posClosingBraces + $strBytes + 3); |
||||
1912 | break; |
||||
1913 | case '"': |
||||
1914 | if ($colonIsToken) { |
||||
1915 | for ($pos = 1; $pos < $len; $pos++) { |
||||
1916 | if ('"' === $str[$pos]) { |
||||
1917 | break; |
||||
1918 | } |
||||
1919 | if ('\\' === $str[$pos] && '"' === $str[$pos + 1]) { |
||||
1920 | $pos++; |
||||
1921 | } |
||||
1922 | if ('\\' === $str[$pos] && '\\' === $str[$pos + 1]) { |
||||
1923 | $pos++; |
||||
1924 | } |
||||
1925 | } |
||||
1926 | if ('"' !== $str[$pos]) { |
||||
1927 | $this->_prot_error("must be a '\"' but is a '" . $str[$pos] . "'!!!!", __LINE__, __FILE__); |
||||
1928 | } |
||||
1929 | $content_size = $pos; |
||||
1930 | $content = mb_substr($str, 1, $pos - 1); |
||||
1931 | //Advance the string |
||||
1932 | $str = mb_substr($str, $pos + 1); |
||||
1933 | } else { |
||||
1934 | for ($pos = 1; $pos < $len; $pos++) { |
||||
1935 | if ('"' === $str[$pos]) { |
||||
1936 | break; |
||||
1937 | } |
||||
1938 | if ('\\' === $str[$pos] && '"' === $str[$pos + 1]) { |
||||
1939 | $pos++; |
||||
1940 | } |
||||
1941 | if ('\\' === $str[$pos] && '\\' === $str[$pos + 1]) { |
||||
1942 | $pos++; |
||||
1943 | } |
||||
1944 | } |
||||
1945 | if ('"' !== $str[$pos]) { |
||||
1946 | $this->_prot_error("must be a '\"' but is a '" . $str[$pos] . "'!!!!", __LINE__, __FILE__); |
||||
1947 | } |
||||
1948 | $content_size = $pos; |
||||
1949 | $content = mb_substr($str, 0, $pos + 1); |
||||
1950 | //Advance the string |
||||
1951 | $str = mb_substr($str, $pos + 1); |
||||
1952 | } |
||||
1953 | break; |
||||
1954 | case "\r": |
||||
1955 | $pos = 1; |
||||
1956 | if ("\n" === $str[1]) { |
||||
1957 | $pos++; |
||||
1958 | } |
||||
1959 | $content_size = $pos; |
||||
1960 | $content = mb_substr($str, 0, $pos); |
||||
1961 | $str = mb_substr($str, $pos); |
||||
1962 | break; |
||||
1963 | case "\n": |
||||
1964 | $pos = 1; |
||||
1965 | $content_size = $pos; |
||||
1966 | $content = mb_substr($str, 0, $pos); |
||||
1967 | $str = mb_substr($str, $pos); |
||||
1968 | break; |
||||
1969 | case '(': |
||||
1970 | if ($parenthesisIsToken) { |
||||
1971 | $pos = 1; |
||||
1972 | $content_size = $pos; |
||||
1973 | $content = mb_substr($str, 0, $pos); |
||||
1974 | $str = mb_substr($str, $pos); |
||||
1975 | } else { |
||||
1976 | $pos = $this->_getClosingBracesPos($str); |
||||
1977 | $content_size = $pos + 1; |
||||
1978 | $content = mb_substr($str, 0, $pos + 1); |
||||
1979 | $str = mb_substr($str, $pos + 1); |
||||
1980 | } |
||||
1981 | break; |
||||
1982 | case ')': |
||||
1983 | $pos = 1; |
||||
1984 | $content_size = $pos; |
||||
1985 | $content = mb_substr($str, 0, $pos); |
||||
1986 | $str = mb_substr($str, $pos); |
||||
1987 | break; |
||||
1988 | case ' ': |
||||
1989 | $pos = 1; |
||||
1990 | $content_size = $pos; |
||||
1991 | $content = mb_substr($str, 0, $pos); |
||||
1992 | $str = mb_substr($str, $pos); |
||||
1993 | break; |
||||
1994 | default: |
||||
1995 | for ($pos = 0; $pos < $len; $pos++) { |
||||
1996 | if (' ' === $str[$pos] || "\r" === $str[$pos] || ')' === $str[$pos] || '(' === $str[$pos] || "\n" === $str[$pos]) { |
||||
1997 | break; |
||||
1998 | } |
||||
1999 | if ('\\' === $str[$pos] && ' ' === $str[$pos + 1]) { |
||||
2000 | $pos++; |
||||
2001 | } |
||||
2002 | if ('\\' === $str[$pos] && '\\' === $str[$pos + 1]) { |
||||
2003 | $pos++; |
||||
2004 | } |
||||
2005 | } |
||||
2006 | //Advance the string |
||||
2007 | if (0 == $pos) { |
||||
2008 | $content_size = 1; |
||||
2009 | $content = mb_substr($str, 0, 1); |
||||
2010 | $str = mb_substr($str, 1); |
||||
2011 | } else { |
||||
2012 | $content_size = $pos; |
||||
2013 | $content = mb_substr($str, 0, $pos); |
||||
2014 | if ($pos < $len) { |
||||
2015 | $str = mb_substr($str, $pos); |
||||
2016 | } else { |
||||
2017 | //if this is the end of the string... exit the switch |
||||
2018 | break; |
||||
2019 | } |
||||
2020 | } |
||||
2021 | break; |
||||
2022 | } |
||||
2023 | |||||
2024 | return $content_size; |
||||
0 ignored issues
–
show
|
|||||
2025 | } |
||||
2026 | |||||
2027 | /** |
||||
2028 | * Utility funcion to display to console the protocol errors |
||||
2029 | * |
||||
2030 | * @param $str |
||||
2031 | * @param $line |
||||
2032 | * @param $file |
||||
2033 | * @param bool $printError |
||||
2034 | * @return string containing the error |
||||
2035 | * @since 1.0 |
||||
2036 | */ |
||||
2037 | public function _prot_error($str, $line, $file, bool $printError = true): string |
||||
2038 | { |
||||
2039 | if ($printError) { |
||||
2040 | echo "$line,$file,PROTOCOL ERROR!:$str\n"; |
||||
0 ignored issues
–
show
In this branch, the function will implicitly return
null which is incompatible with the type-hinted return string . Consider adding a return statement or allowing null as return value.
For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example: interface ReturnsInt {
public function returnsIntHinted(): int;
}
class MyClass implements ReturnsInt {
public function returnsIntHinted(): int
{
if (foo()) {
return 123;
}
// here: null is implicitly returned
}
}
![]() |
|||||
2041 | } |
||||
0 ignored issues
–
show
The function implicitly returns
null when the if condition on line 2039 is false . This is incompatible with the type-hinted return string . Consider adding a return statement or allowing null as return value.
For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example: interface ReturnsInt {
public function returnsIntHinted(): int;
}
class MyClass implements ReturnsInt {
public function returnsIntHinted(): int
{
if (foo()) {
return 123;
}
// here: null is implicitly returned
}
}
![]() |
|||||
2042 | } |
||||
2043 | |||||
2044 | /** |
||||
2045 | * @param string $startDelim |
||||
2046 | * @param string $stopDelim |
||||
2047 | * @param mixed $str |
||||
2048 | * @return array |
||||
2049 | */ |
||||
2050 | public function _getEXTarray(&$str, string $startDelim = '(', string $stopDelim = ')'): array |
||||
2051 | { |
||||
2052 | /* I let choose the $startDelim and $stopDelim to allow parsing |
||||
2053 | the OK response so I also can parse a response like this |
||||
2054 | * OK [UIDNEXT 150] Predicted next UID |
||||
2055 | */ |
||||
2056 | $this->_getNextToken($str, $parenthesis); |
||||
2057 | if ($parenthesis != $startDelim) { |
||||
2058 | $this->_prot_error("must be a '$startDelim' but is a '$parenthesis' !!!!", __LINE__, __FILE__); |
||||
2059 | } |
||||
2060 | $parenthesis = ''; |
||||
2061 | $struct_arr = []; |
||||
2062 | while ($parenthesis != $stopDelim && '' != $str) { |
||||
2063 | // The command |
||||
2064 | $this->_getNextToken($str, $token); |
||||
2065 | $token = \mb_strtoupper($token); |
||||
2066 | |||||
2067 | if (false !== ($ret = $this->_retrParsedResponse($str, $token))) { |
||||
2068 | //$struct_arr[$token] = $ret; |
||||
2069 | $struct_arr = array_merge($struct_arr, $ret); |
||||
0 ignored issues
–
show
It seems like
$ret can also be of type string ; however, parameter $arrays of array_merge() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
2070 | } |
||||
2071 | |||||
2072 | $parenthesis = $token; |
||||
2073 | }//While |
||||
2074 | |||||
2075 | if ($parenthesis != $stopDelim) { |
||||
2076 | $this->_prot_error("1_must be a '$stopDelim' but is a '$parenthesis' !!!!", __LINE__, __FILE__); |
||||
2077 | } |
||||
2078 | |||||
2079 | return $struct_arr; |
||||
2080 | } |
||||
2081 | |||||
2082 | /** |
||||
2083 | * @param $token |
||||
2084 | * @param null $previousToken |
||||
0 ignored issues
–
show
|
|||||
2085 | * @param mixed $str |
||||
2086 | * @return array|array[]|false|null[]|string|string[]|\string[][] |
||||
2087 | */ |
||||
2088 | public function _retrParsedResponse(&$str, $token, $previousToken = null) |
||||
2089 | { |
||||
2090 | //echo "\n\nTOKEN:$token\r\n"; |
||||
2091 | switch ($token) { |
||||
2092 | case 'RFC822.SIZE': |
||||
2093 | return [$token => $this->_parseOneStringResponse($str, __LINE__, __FILE__)]; |
||||
2094 | // case "RFC822.TEXT" : |
||||
2095 | |||||
2096 | // case "RFC822.HEADER" : |
||||
2097 | |||||
2098 | case 'RFC822': |
||||
2099 | return [$token => $this->_parseContentresponse($str, $token)]; |
||||
2100 | case 'FLAGS': |
||||
2101 | |||||
2102 | case 'PERMANENTFLAGS': |
||||
2103 | return [$token => $this->_parseFLAGSresponse($str)]; |
||||
2104 | case 'ENVELOPE': |
||||
2105 | return [$token => $this->_parseENVELOPEresponse($str)]; |
||||
2106 | case 'EXPUNGE': |
||||
2107 | return false; |
||||
2108 | case 'UID': |
||||
2109 | |||||
2110 | case 'UIDNEXT': |
||||
2111 | |||||
2112 | case 'UIDVALIDITY': |
||||
2113 | |||||
2114 | case 'UNSEEN': |
||||
2115 | |||||
2116 | case 'MESSAGES': |
||||
2117 | |||||
2118 | case 'UIDNEXT': |
||||
2119 | |||||
2120 | case 'UIDVALIDITY': |
||||
2121 | |||||
2122 | case 'UNSEEN': |
||||
2123 | |||||
2124 | case 'INTERNALDATE': |
||||
2125 | return [$token => $this->_parseOneStringResponse($str, __LINE__, __FILE__)]; |
||||
2126 | case 'BODY': |
||||
2127 | |||||
2128 | case 'BODYSTRUCTURE': |
||||
2129 | return [$token => $this->_parseBodyResponse($str, $token)]; |
||||
2130 | case 'RECENT': |
||||
2131 | if (null !== $previousToken) { |
||||
0 ignored issues
–
show
|
|||||
2132 | $aux['RECENT'] = $previousToken; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2133 | |||||
2134 | return $aux; |
||||
2135 | } |
||||
2136 | |||||
2137 | return [$token => $this->_parseOneStringResponse($str, __LINE__, __FILE__)]; |
||||
2138 | case 'EXISTS': |
||||
2139 | return [$token => $previousToken]; |
||||
2140 | case 'READ-WRITE': |
||||
2141 | |||||
2142 | case 'READ-ONLY': |
||||
2143 | return [$token => $token]; |
||||
2144 | case 'QUOTA': |
||||
2145 | /* |
||||
2146 | A tipical GETQUOTA DIALOG IS AS FOLLOWS |
||||
2147 | |||||
2148 | C: A0004 GETQUOTA user.damian |
||||
2149 | S: * QUOTA user.damian (STORAGE 1781460 4000000) |
||||
2150 | S: A0004 OK Completed |
||||
2151 | */ |
||||
2152 | |||||
2153 | $mailbox = $this->_parseOneStringResponse($str, __LINE__, __FILE__); |
||||
2154 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2155 | $this->_parseString($str, '(', __LINE__, __FILE__); |
||||
2156 | |||||
2157 | $ret_aux = ['MAILBOX' => $this->utf_7_decode($mailbox)]; |
||||
2158 | $this->_getNextToken($str, $quota_resp); |
||||
2159 | if (false === ($ext = $this->_retrParsedResponse($str, $quota_resp))) { |
||||
2160 | $this->_prot_error('bogus response!!!!', __LINE__, __FILE__); |
||||
2161 | } |
||||
2162 | $ret_aux = array_merge($ret_aux, $ext); |
||||
0 ignored issues
–
show
It seems like
$ext can also be of type false and string ; however, parameter $arrays of array_merge() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
2163 | |||||
2164 | $this->_getNextToken($str, $separator); |
||||
2165 | if (')' === $separator) { |
||||
2166 | return [$token => $ret_aux]; |
||||
2167 | } |
||||
2168 | |||||
2169 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2170 | |||||
2171 | $this->_getNextToken($str, $quota_resp); |
||||
2172 | if (false === ($ext = $this->_retrParsedResponse($str, $quota_resp))) { |
||||
2173 | $this->_prot_error('bogus response!!!!', __LINE__, __FILE__); |
||||
2174 | } |
||||
2175 | $ret_aux = array_merge($ret_aux, $ext); |
||||
2176 | |||||
2177 | $this->_parseString($str, ')', __LINE__, __FILE__); |
||||
2178 | |||||
2179 | return [$token => $ret_aux]; |
||||
2180 | case 'QUOTAROOT': |
||||
2181 | /* |
||||
2182 | A tipical GETQUOTA DIALOG IS AS FOLLOWS |
||||
2183 | |||||
2184 | C: A0004 GETQUOTA user.damian |
||||
2185 | S: * QUOTA user.damian (STORAGE 1781460 4000000) |
||||
2186 | S: A0004 OK Completed |
||||
2187 | */ $mailbox = $this->utf_7_decode($this->_parseOneStringResponse($str, __LINE__, __FILE__)); |
||||
2188 | |||||
2189 | $str_line = rtrim(mb_substr($this->_getToEOL($str, false), 0)); |
||||
2190 | |||||
2191 | $quotaroot = $this->_parseOneStringResponse($str_line, __LINE__, __FILE__); |
||||
2192 | $ret = @['MAILBOX' => $this->utf_7_decode($mailbox), $token => $quotaroot]; |
||||
2193 | |||||
2194 | return [$token => $ret]; |
||||
2195 | case 'STORAGE': |
||||
2196 | $used = $this->_parseOneStringResponse($str, __LINE__, __FILE__); |
||||
2197 | $qmax = $this->_parseOneStringResponse($str, __LINE__, __FILE__); |
||||
2198 | |||||
2199 | return [$token => ['USED' => $used, 'QMAX' => $qmax]]; |
||||
2200 | case 'MESSAGE': |
||||
2201 | $mused = $this->_parseOneStringResponse($str, __LINE__, __FILE__); |
||||
2202 | $mmax = $this->_parseOneStringResponse($str, __LINE__, __FILE__); |
||||
2203 | |||||
2204 | return [$token => ['MUSED' => $mused, 'MMAX' => $mmax]]; |
||||
2205 | case 'FETCH': |
||||
2206 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2207 | // Get the parsed pathenthesis |
||||
2208 | $struct_arr = $this->_getEXTarray($str); |
||||
2209 | |||||
2210 | return $struct_arr; |
||||
2211 | case 'CAPABILITY': |
||||
2212 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2213 | $str_line = rtrim(mb_substr($this->_getToEOL($str, false), 0)); |
||||
2214 | $struct_arr['CAPABILITIES'] = explode(' ', $str_line); |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2215 | |||||
2216 | return [$token => $struct_arr]; |
||||
2217 | case 'STATUS': |
||||
2218 | $mailbox = $this->_parseOneStringResponse($str, __LINE__, __FILE__); |
||||
2219 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2220 | $ext = $this->_getEXTarray($str); |
||||
2221 | $struct_arr['MAILBOX'] = $this->utf_7_decode($mailbox); |
||||
2222 | $struct_arr['ATTRIBUTES'] = $ext; |
||||
2223 | |||||
2224 | return [$token => $struct_arr]; |
||||
2225 | case 'LIST': |
||||
2226 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2227 | $params_arr = $this->_arrayfy_content($str); |
||||
2228 | |||||
2229 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2230 | $this->_getNextToken($str, $hierarchydelim); |
||||
2231 | |||||
2232 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2233 | $this->_getNextToken($str, $mailbox_name); |
||||
2234 | |||||
2235 | $result_array = ['NAME_ATTRIBUTES' => $params_arr, 'HIERACHY_DELIMITER' => $hierarchydelim, 'MAILBOX_NAME' => $this->utf_7_decode($mailbox_name)]; |
||||
2236 | |||||
2237 | return [$token => $result_array]; |
||||
2238 | case 'LSUB': |
||||
2239 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2240 | $params_arr = $this->_arrayfy_content($str); |
||||
2241 | |||||
2242 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2243 | $this->_getNextToken($str, $hierarchydelim); |
||||
2244 | |||||
2245 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2246 | $this->_getNextToken($str, $mailbox_name); |
||||
2247 | |||||
2248 | $result_array = ['NAME_ATTRIBUTES' => $params_arr, 'HIERACHY_DELIMITER' => $hierarchydelim, 'MAILBOX_NAME' => $this->utf_7_decode($mailbox_name)]; |
||||
2249 | |||||
2250 | return [$token => $result_array]; |
||||
2251 | case 'SEARCH': |
||||
2252 | $str_line = rtrim(mb_substr($this->_getToEOL($str, false), 1)); |
||||
2253 | $struct_arr['SEARCH_LIST'] = explode(' ', $str_line); |
||||
2254 | if (1 == count($struct_arr['SEARCH_LIST']) && '' == $struct_arr['SEARCH_LIST'][0]) { |
||||
2255 | $struct_arr['SEARCH_LIST'] = null; |
||||
2256 | } |
||||
2257 | |||||
2258 | return [$token => $struct_arr]; |
||||
2259 | case 'OK': |
||||
2260 | /* TODO: |
||||
2261 | parse the [ .... ] part of the response, use the method |
||||
2262 | _getEXTarray(&$str,'[',$stopDelim=']') |
||||
2263 | |||||
2264 | */ $str_line = rtrim(mb_substr($this->_getToEOL($str, false), 1)); |
||||
2265 | if ('[' === $str_line[0]) { |
||||
2266 | $braceLen = $this->_getClosingBracesPos($str_line, '[', ']'); |
||||
2267 | $str_aux = '(' . mb_substr($str_line, 1, $braceLen - 1) . ')'; |
||||
2268 | $ext_arr = $this->_getEXTarray($str_aux); |
||||
2269 | //$ext_arr=array($token=>$this->_getEXTarray($str_aux)); |
||||
2270 | } else { |
||||
2271 | $ext_arr = $str_line; |
||||
2272 | //$ext_arr=array($token=>$str_line); |
||||
2273 | } |
||||
2274 | $result_array = $ext_arr; |
||||
2275 | |||||
2276 | return $result_array; |
||||
2277 | case 'NO': |
||||
2278 | /* TODO: |
||||
2279 | parse the [ .... ] part of the response, use the method |
||||
2280 | _getEXTarray(&$str,'[',$stopDelim=']') |
||||
2281 | |||||
2282 | */ |
||||
2283 | |||||
2284 | $str_line = rtrim(mb_substr($this->_getToEOL($str, false), 1)); |
||||
2285 | $result_array[] = @['COMMAND' => $token, 'EXT' => $str_line]; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2286 | |||||
2287 | return $result_array; |
||||
2288 | case 'BAD': |
||||
2289 | /* TODO: |
||||
2290 | parse the [ .... ] part of the response, use the method |
||||
2291 | _getEXTarray(&$str,'[',$stopDelim=']') |
||||
2292 | |||||
2293 | */ |
||||
2294 | |||||
2295 | $str_line = rtrim(mb_substr($this->_getToEOL($str, false), 1)); |
||||
2296 | $result_array[] = ['COMMAND' => $token, 'EXT' => $str_line]; |
||||
2297 | |||||
2298 | return $result_array; |
||||
2299 | case 'BYE': |
||||
2300 | /* TODO: |
||||
2301 | parse the [ .... ] part of the response, use the method |
||||
2302 | _getEXTarray(&$str,'[',$stopDelim=']') |
||||
2303 | |||||
2304 | */ |
||||
2305 | |||||
2306 | $str_line = rtrim(mb_substr($this->_getToEOL($str, false), 1)); |
||||
2307 | $result_array[] = ['COMMAND' => $command, 'EXT' => $str_line]; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2308 | |||||
2309 | return $result_array; |
||||
2310 | case 'LISTRIGHTS': |
||||
2311 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2312 | $this->_getNextToken($str, $mailbox); |
||||
2313 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2314 | $this->_getNextToken($str, $user); |
||||
2315 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2316 | $this->_getNextToken($str, $granted); |
||||
2317 | |||||
2318 | $ungranted = explode(' ', rtrim(mb_substr($this->_getToEOL($str, false), 1))); |
||||
2319 | |||||
2320 | $result_array = @['MAILBOX' => $this->utf_7_decode($mailbox), 'USER' => $user, 'GRANTED' => $granted, 'UNGRANTED' => $ungranted]; |
||||
2321 | |||||
2322 | return $result_array; |
||||
2323 | case 'MYRIGHTS': |
||||
2324 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2325 | $this->_getNextToken($str, $mailbox); |
||||
2326 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2327 | $this->_getNextToken($str, $granted); |
||||
2328 | |||||
2329 | $result_array = ['MAILBOX' => $this->utf_7_decode($mailbox), 'GRANTED' => $granted]; |
||||
2330 | |||||
2331 | return $result_array; |
||||
2332 | case 'ACL': |
||||
2333 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2334 | $this->_getNextToken($str, $mailbox); |
||||
2335 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2336 | $acl_arr = explode(' ', rtrim(mb_substr($this->_getToEOL($str, false), 0))); |
||||
2337 | |||||
2338 | for ($i = 0, $iMax = count($acl_arr); $i < $iMax; $i += 2) { |
||||
2339 | $arr[] = ['USER' => $acl_arr[$i], 'RIGHTS' => $acl_arr[$i + 1]]; |
||||
2340 | } |
||||
2341 | |||||
2342 | $result_array = ['MAILBOX' => $this->utf_7_decode($mailbox), 'USERS' => $arr]; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2343 | |||||
2344 | return $result_array; |
||||
2345 | case 'ANNOTATION': |
||||
2346 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2347 | $this->_getNextToken($str, $mailbox); |
||||
2348 | |||||
2349 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2350 | $this->_getNextToken($str, $entry); |
||||
2351 | |||||
2352 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2353 | $attrs = $this->_arrayfy_content($str); |
||||
2354 | |||||
2355 | $result_array = ['MAILBOX' => $mailbox, 'ENTRY' => $entry, 'ATTRIBUTES' => $attrs]; |
||||
2356 | |||||
2357 | return $result_array; |
||||
2358 | case '': |
||||
2359 | $this->_prot_error('PROTOCOL ERROR!:str empty!!', __LINE__, __FILE__); |
||||
2360 | break; |
||||
2361 | case '(': |
||||
2362 | $this->_prot_error('OPENING PARENTHESIS ERROR!!!!!!!!!!!!!!!!!', __LINE__, __FILE__); |
||||
2363 | break; |
||||
2364 | case ')': |
||||
2365 | //"CLOSING PARENTHESIS BREAK!!!!!!!" |
||||
2366 | break; |
||||
2367 | case "\r\n": |
||||
2368 | $this->_prot_error('BREAK!!!!!!!!!!!!!!!!!', __LINE__, __FILE__); |
||||
2369 | break; |
||||
2370 | case ' ': |
||||
2371 | // this can happen and we just ignore it |
||||
2372 | // This happens when - for example - fetch returns more than 1 parammeter |
||||
2373 | // for example you ask to get RFC822.SIZE and UID |
||||
2374 | //$this->_prot_error("SPACE BREAK!!!!!!!!!!!!!!!!!" , __LINE__ , __FILE__ ); |
||||
2375 | break; |
||||
2376 | default: |
||||
2377 | $body_token = \mb_strtoupper(mb_substr($token, 0, 5)); |
||||
2378 | //echo "BODYYYYYYY: $body_token\n"; |
||||
2379 | $rfc822_token = \mb_strtoupper(mb_substr($token, 0, 7)); |
||||
2380 | //echo "BODYYYYYYY: $rfc822_token|$token\n"; |
||||
2381 | |||||
2382 | if ('BODY[' === $body_token || 'BODY.' === $body_token || 'RFC822.' === $rfc822_token) { |
||||
2383 | //echo "TOKEN:$token\n"; |
||||
2384 | //$this->_getNextToken( $str , $mailbox ); |
||||
2385 | return [$token => $this->_parseContentresponse($str, $token)]; |
||||
2386 | } |
||||
2387 | $this->_prot_error("UNIMPLEMMENTED! I don't know the parameter '$token' !!!", __LINE__, __FILE__); |
||||
2388 | |||||
2389 | break; |
||||
2390 | } |
||||
2391 | |||||
2392 | return false; |
||||
2393 | } |
||||
2394 | |||||
2395 | /* |
||||
2396 | * Verifies that the next character IS a space |
||||
2397 | */ |
||||
2398 | |||||
2399 | /** |
||||
2400 | * @param $line |
||||
2401 | * @param $file |
||||
2402 | * @param bool $printError |
||||
2403 | * @param mixed $str |
||||
2404 | * @return mixed|string |
||||
2405 | */ |
||||
2406 | public function _parseSpace(&$str, $line, $file, bool $printError = true) |
||||
2407 | { |
||||
2408 | /* |
||||
2409 | This code repeats a lot in this class |
||||
2410 | so i make it a function to make all the code shorter |
||||
2411 | */ |
||||
2412 | $this->_getNextToken($str, $space); |
||||
2413 | if (' ' !== $space) { |
||||
2414 | $this->_prot_error("must be a ' ' but is a '$space' !!!!", $line, $file, $printError); |
||||
2415 | } |
||||
2416 | |||||
2417 | return $space; |
||||
2418 | } |
||||
2419 | |||||
2420 | /** |
||||
2421 | * @param string $str |
||||
2422 | * @param string $char |
||||
2423 | * @param string $line |
||||
2424 | * @param string $file |
||||
2425 | * @return mixed |
||||
2426 | */ |
||||
2427 | public function _parseString(&$str, $char, $line, $file) |
||||
2428 | { |
||||
2429 | /* |
||||
2430 | This code repeats a lot in this class |
||||
2431 | so i make it a function to make all the code shorter |
||||
2432 | */ |
||||
2433 | $this->_getNextToken($str, $char_aux); |
||||
2434 | if (mb_strtoupper($char_aux) != \mb_strtoupper($char)) { |
||||
2435 | $this->_prot_error("must be a $char but is a '$char_aux' !!!!", $line, $file); |
||||
2436 | } |
||||
2437 | |||||
2438 | return $char_aux; |
||||
2439 | } |
||||
2440 | |||||
2441 | /** |
||||
2442 | * @param null $cmdid |
||||
0 ignored issues
–
show
|
|||||
2443 | * @param mixed $str |
||||
2444 | * @return array |
||||
2445 | */ |
||||
2446 | public function _genericImapResponseParser(&$str, $cmdid = null): array |
||||
2447 | { |
||||
2448 | $result_array = []; |
||||
2449 | if ($this->_unParsedReturn) { |
||||
2450 | $unparsed_str = $str; |
||||
2451 | } |
||||
2452 | |||||
2453 | $this->_getNextToken($str, $token); |
||||
2454 | |||||
2455 | while ($token != $cmdid && '' != $str) { |
||||
2456 | if ('+' == $token) { |
||||
2457 | //if the token is + ignore the line |
||||
2458 | // TODO: verify that this is correct!!! |
||||
2459 | $this->_getToEOL($str); |
||||
2460 | $this->_getNextToken($str, $token); |
||||
2461 | } |
||||
2462 | |||||
2463 | $this->_parseString($str, ' ', __LINE__, __FILE__); |
||||
2464 | |||||
2465 | $this->_getNextToken($str, $token); |
||||
2466 | if ('+' == $token) { |
||||
2467 | $this->_getToEOL($str); |
||||
2468 | $this->_getNextToken($str, $token); |
||||
2469 | } elseif (is_numeric($token)) { |
||||
2470 | // The token is a NUMBER so I store it |
||||
2471 | $msg_nro = $token; |
||||
2472 | $this->_parseSpace($str, __LINE__, __FILE__); |
||||
2473 | |||||
2474 | // I get the command |
||||
2475 | $this->_getNextToken($str, $command); |
||||
2476 | |||||
2477 | if (false === ($ext_arr = $this->_retrParsedResponse($str, $command, $msg_nro))) { |
||||
2478 | // if this bogus response cis a FLAGS () or EXPUNGE response |
||||
2479 | // the ignore it |
||||
2480 | if ('FLAGS' !== $command && 'EXPUNGE' !== $command) { |
||||
2481 | $this->_prot_error('bogus response!!!!', __LINE__, __FILE__, false); |
||||
2482 | } |
||||
2483 | } |
||||
2484 | $result_array[] = ['COMMAND' => $command, 'NRO' => $msg_nro, 'EXT' => $ext_arr]; |
||||
2485 | } else { |
||||
2486 | // OK the token is not a NUMBER so it MUST be a COMMAND |
||||
2487 | $command = $token; |
||||
2488 | |||||
2489 | /* Call the parser return the array |
||||
2490 | take care of bogus responses! |
||||
2491 | */ |
||||
2492 | |||||
2493 | if (false === ($ext_arr = $this->_retrParsedResponse($str, $command))) { |
||||
2494 | $this->_prot_error("bogus response!!!! (COMMAND:$command)", __LINE__, __FILE__); |
||||
2495 | } |
||||
2496 | $result_array[] = ['COMMAND' => $command, 'EXT' => $ext_arr]; |
||||
2497 | } |
||||
2498 | |||||
2499 | $this->_getNextToken($str, $token); |
||||
2500 | |||||
2501 | $token = \mb_strtoupper($token); |
||||
2502 | if ("\r\n" !== $token && '' != $token) { |
||||
2503 | $this->_prot_error("PARSE ERROR!!! must be a '\\r\\n' here but is a '$token'!!!! (getting the next line)|STR:|$str|", __LINE__, __FILE__); |
||||
2504 | } |
||||
2505 | $this->_getNextToken($str, $token); |
||||
2506 | |||||
2507 | if ('+' == $token) { |
||||
2508 | //if the token is + ignore the line |
||||
2509 | // TODO: verify that this is correct!!! |
||||
2510 | $this->_getToEOL($str); |
||||
2511 | $this->_getNextToken($str, $token); |
||||
2512 | } |
||||
2513 | }//While |
||||
2514 | // OK we finish the UNTAGGED Response now we must parse the FINAL TAGGED RESPONSE |
||||
2515 | //TODO: make this a litle more elegant! |
||||
2516 | |||||
2517 | $this->_parseSpace($str, __LINE__, __FILE__, false); |
||||
2518 | |||||
2519 | $this->_getNextToken($str, $cmd_status); |
||||
2520 | |||||
2521 | $str_line = rtrim(mb_substr($this->_getToEOL($str), 1)); |
||||
2522 | |||||
2523 | $response['RESPONSE'] = ['CODE' => $cmd_status, 'STR_CODE' => $str_line, 'CMDID' => $cmdid]; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2524 | |||||
2525 | $ret = $response; |
||||
2526 | if (!empty($result_array)) { |
||||
2527 | $ret = array_merge($ret, ['PARSED' => $result_array]); |
||||
2528 | } |
||||
2529 | |||||
2530 | if ($this->_unParsedReturn) { |
||||
2531 | $unparsed['UNPARSED'] = $unparsed_str; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||||
2532 | $ret = array_merge($ret, $unparsed); |
||||
2533 | } |
||||
2534 | |||||
2535 | if (isset($status_arr)) { |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2536 | $status['STATUS'] = $status_arr; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
2537 | $ret = array_merge($ret, $status); |
||||
2538 | } |
||||
2539 | |||||
2540 | return $ret; |
||||
2541 | } |
||||
2542 | |||||
2543 | /** |
||||
2544 | * @param string $command |
||||
2545 | * @param string $params |
||||
2546 | * @return array|\PEAR_Error |
||||
2547 | */ |
||||
2548 | public function _genericCommand($command, string $params = '') |
||||
2549 | { |
||||
2550 | if (!$this->_connected) { |
||||
2551 | return new PEAR_Error("not connected! (CMD:$command)"); |
||||
2552 | } |
||||
2553 | $cmdid = $this->_getCmdId(); |
||||
2554 | $this->_putCMD($cmdid, $command, $params); |
||||
2555 | $args = $this->_getRawResponse($cmdid); |
||||
2556 | |||||
2557 | return $this->_genericImapResponseParser($args, $cmdid); |
||||
2558 | } |
||||
2559 | |||||
2560 | /** |
||||
2561 | * @param string $str |
||||
2562 | * @return \PEAR_Error|string |
||||
2563 | */ |
||||
2564 | public function utf_7_encode(string $str) |
||||
2565 | { |
||||
2566 | if (!$this->_useUTF_7) { |
||||
2567 | return $str; |
||||
2568 | } |
||||
2569 | //return imap_utf7_encode($str); |
||||
2570 | |||||
2571 | $encoded_utf7 = ''; |
||||
2572 | $base64_part = ''; |
||||
2573 | if (is_array($str)) { |
||||
0 ignored issues
–
show
|
|||||
2574 | return new PEAR_Error('error'); |
||||
2575 | } |
||||
2576 | |||||
2577 | for ($i = 0, $iMax = mb_strlen($str); $i < $iMax; ++$i) { |
||||
2578 | //those chars should be base64 encoded |
||||
2579 | if (((ord($str[$i]) >= 39) && (ord($str[$i]) <= 126)) || ((ord($str[$i]) >= 32) && (ord($str[$i]) <= 37))) { |
||||
2580 | if ($base64_part) { |
||||
2581 | $encoded_utf7 = sprintf('%s&%s-', $encoded_utf7, str_replace('=', '', base64_encode($base64_part))); |
||||
2582 | $base64_part = ''; |
||||
2583 | } |
||||
2584 | $encoded_utf7 = sprintf('%s%s', $encoded_utf7, $str[$i]); |
||||
2585 | } else { |
||||
2586 | //handle & |
||||
2587 | if (38 == ord($str[$i])) { |
||||
2588 | if ($base64_part) { |
||||
2589 | $encoded_utf7 = sprintf('%s&%s-', $encoded_utf7, str_replace('=', '', base64_encode($base64_part))); |
||||
2590 | $base64_part = ''; |
||||
2591 | } |
||||
2592 | $encoded_utf7 = sprintf('%s&-', $encoded_utf7); |
||||
2593 | } else { |
||||
2594 | $base64_part = sprintf('%s%s', $base64_part, $str[$i]); |
||||
2595 | //$base64_part = sprintf("%s%s%s",$base64_part , chr(0) , $str[$i]); |
||||
2596 | } |
||||
2597 | } |
||||
2598 | } |
||||
2599 | if ($base64_part) { |
||||
2600 | $encoded_utf7 = sprintf('%s&%s-', $encoded_utf7, str_replace('=', '', base64_encode($base64_part))); |
||||
2601 | $base64_part = ''; |
||||
0 ignored issues
–
show
|
|||||
2602 | } |
||||
2603 | |||||
2604 | return $encoded_utf7; |
||||
2605 | } |
||||
2606 | |||||
2607 | /** |
||||
2608 | * @param string $str |
||||
2609 | * @return string |
||||
2610 | */ |
||||
2611 | public function utf_7_decode($str): string |
||||
2612 | { |
||||
2613 | if (!$this->_useUTF_7) { |
||||
2614 | return $str; |
||||
2615 | } |
||||
2616 | |||||
2617 | //return imap_utf7_decode($str); |
||||
2618 | |||||
2619 | $base64_part = ''; |
||||
2620 | $decoded_utf7 = ''; |
||||
2621 | |||||
2622 | for ($i = 0, $iMax = mb_strlen($str); $i < $iMax; ++$i) { |
||||
2623 | if ('' !== $base64_part) { |
||||
2624 | if ('-' == $str[$i]) { |
||||
2625 | if ('&' === $base64_part) { |
||||
2626 | $decoded_utf7 = sprintf('%s&', $decoded_utf7); |
||||
2627 | } else { |
||||
2628 | $next_part_decoded = base64_decode(mb_substr($base64_part, 1), true); |
||||
2629 | $decoded_utf7 = sprintf('%s%s', $decoded_utf7, $next_part_decoded); |
||||
2630 | } |
||||
2631 | $base64_part = ''; |
||||
2632 | } else { |
||||
2633 | $base64_part = sprintf('%s%s', $base64_part, $str[$i]); |
||||
2634 | } |
||||
2635 | } else { |
||||
2636 | if ('&' === $str[$i]) { |
||||
2637 | $base64_part = '&'; |
||||
2638 | } else { |
||||
2639 | $decoded_utf7 = sprintf('%s%s', $decoded_utf7, $str[$i]); |
||||
2640 | } |
||||
2641 | } |
||||
2642 | } |
||||
2643 | |||||
2644 | return $decoded_utf7; |
||||
2645 | } |
||||
2646 | }//Class |
||||
2647 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..