comparison vendor/pear/net_sieve/Sieve.php @ 35:05c4c32948af

.hgignore: add vendor tree composer.json: new packages plugins/thunderbird_labels/thunderbird_labels.php: change hook and RFC822 use wrt whitelisting to avoid deprecated stuff index.php: commented debugging hooks others: new releases of vendor packages?
author Charlie Root
date Thu, 30 Aug 2018 16:21:59 -0400
parents 1e000243b222
children
comparison
equal deleted inserted replaced
34:50ac5484d514 35:05c4c32948af
44 44
45 require_once 'PEAR.php'; 45 require_once 'PEAR.php';
46 require_once 'Net/Socket.php'; 46 require_once 'Net/Socket.php';
47 47
48 /** 48 /**
49 * TODO 49 * Disconnected state
50 * 50 *
51 * o supportsAuthMech()
52 */
53
54 /**
55 * Disconnected state
56 * @const NET_SIEVE_STATE_DISCONNECTED 51 * @const NET_SIEVE_STATE_DISCONNECTED
57 */ 52 */
58 define('NET_SIEVE_STATE_DISCONNECTED', 1, true); 53 define('NET_SIEVE_STATE_DISCONNECTED', 1, true);
59 54
60 /** 55 /**
61 * Authorisation state 56 * Authorisation state
57 *
62 * @const NET_SIEVE_STATE_AUTHORISATION 58 * @const NET_SIEVE_STATE_AUTHORISATION
63 */ 59 */
64 define('NET_SIEVE_STATE_AUTHORISATION', 2, true); 60 define('NET_SIEVE_STATE_AUTHORISATION', 2, true);
65 61
66 /** 62 /**
67 * Transaction state 63 * Transaction state
64 *
68 * @const NET_SIEVE_STATE_TRANSACTION 65 * @const NET_SIEVE_STATE_TRANSACTION
69 */ 66 */
70 define('NET_SIEVE_STATE_TRANSACTION', 3, true); 67 define('NET_SIEVE_STATE_TRANSACTION', 3, true);
71 68
72 69
77 * @package Net_Sieve 74 * @package Net_Sieve
78 * @author Richard Heyes <richard@phpguru.org> 75 * @author Richard Heyes <richard@phpguru.org>
79 * @author Damian Fernandez Sosa <damlists@cnba.uba.ar> 76 * @author Damian Fernandez Sosa <damlists@cnba.uba.ar>
80 * @author Anish Mistry <amistry@am-productions.biz> 77 * @author Anish Mistry <amistry@am-productions.biz>
81 * @author Jan Schneider <jan@horde.org> 78 * @author Jan Schneider <jan@horde.org>
79 * @author Neil Munday <neil@mundayweb.com>
82 * @copyright 2002-2003 Richard Heyes 80 * @copyright 2002-2003 Richard Heyes
83 * @copyright 2006-2008 Anish Mistry 81 * @copyright 2006-2008 Anish Mistry
84 * @license http://www.opensource.org/licenses/bsd-license.php BSD 82 * @license http://www.opensource.org/licenses/bsd-license.php BSD
85 * @version Release: @package_version@ 83 * @version Release: @package_version@
86 * @link http://pear.php.net/package/Net_Sieve 84 * @link http://pear.php.net/package/Net_Sieve
101 var $supportedAuthMethods = array( 99 var $supportedAuthMethods = array(
102 'DIGEST-MD5', 100 'DIGEST-MD5',
103 'CRAM-MD5', 101 'CRAM-MD5',
104 'EXTERNAL', 102 'EXTERNAL',
105 'PLAIN' , 103 'PLAIN' ,
106 'LOGIN' 104 'LOGIN',
105 'GSSAPI'
107 ); 106 );
108 107
109 /** 108 /**
110 * SASL authentication methods that require Auth_SASL. 109 * SASL authentication methods that require Auth_SASL.
111 * 110 *
191 * Maximum number of referral loops 190 * Maximum number of referral loops
192 * 191 *
193 * @var array 192 * @var array
194 */ 193 */
195 var $_maxReferralCount = 15; 194 var $_maxReferralCount = 15;
195
196 /**
197 * Kerberos service principal to use for GSSAPI authentication.
198 *
199 * @var string
200 */
201 var $_gssapiPrincipal = null;
202
203 /**
204 * Kerberos service cname to use for GSSAPI authentication.
205 *
206 * @var string
207 */
208 var $_gssapiCN = null;
196 209
197 /** 210 /**
198 * Constructor. 211 * Constructor.
199 * 212 *
200 * Sets up the object, connects to the server and logs in. Stores any 213 * Sets up the object, connects to the server and logs in. Stores any
214 * socket is already open. 227 * socket is already open.
215 * @param boolean $useTLS Use TLS if available. 228 * @param boolean $useTLS Use TLS if available.
216 * @param array $options Additional options for 229 * @param array $options Additional options for
217 * stream_context_create(). 230 * stream_context_create().
218 * @param mixed $handler A callback handler for the debug output. 231 * @param mixed $handler A callback handler for the debug output.
232 * @param string $principal Kerberos service principal to use
233 * with GSSAPI authentication.
234 * @param string $cname Kerberos service cname to use
235 * with GSSAPI authentication.
219 */ 236 */
220 function __construct($user = null, $pass = null, $host = 'localhost', 237 function __construct($user = null, $pass = null, $host = 'localhost',
221 $port = 2000, $logintype = '', $euser = '', 238 $port = 2000, $logintype = '', $euser = '',
222 $debug = false, $bypassAuth = false, $useTLS = true, 239 $debug = false, $bypassAuth = false, $useTLS = true,
223 $options = null, $handler = null 240 $options = null, $handler = null, $principal = null, $cname = null
224 ) { 241 ) {
225 $this->_pear = new PEAR(); 242 $this->_pear = new PEAR();
226 $this->_state = NET_SIEVE_STATE_DISCONNECTED; 243 $this->_state = NET_SIEVE_STATE_DISCONNECTED;
227 $this->_data['user'] = $user; 244 $this->_data['user'] = $user;
228 $this->_data['pass'] = $pass; 245 $this->_data['pass'] = $pass;
232 $this->_data['euser'] = $euser; 249 $this->_data['euser'] = $euser;
233 $this->_sock = new Net_Socket(); 250 $this->_sock = new Net_Socket();
234 $this->_bypassAuth = $bypassAuth; 251 $this->_bypassAuth = $bypassAuth;
235 $this->_useTLS = $useTLS; 252 $this->_useTLS = $useTLS;
236 $this->_options = (array) $options; 253 $this->_options = (array) $options;
254 $this->_gssapiPrincipal = $principal;
255 $this->_gssapiCN = $cname;
256
237 $this->setDebug($debug, $handler); 257 $this->setDebug($debug, $handler);
238 258
239 /* Try to include the Auth_SASL package. If the package is not 259 /* Try to include the Auth_SASL package. If the package is not
240 * available, we disable the authentication methods that depend upon 260 * available, we disable the authentication methods that depend upon
241 * it. */ 261 * it. */
275 $this->_debug = $debug; 295 $this->_debug = $debug;
276 $this->_debug_handler = $handler; 296 $this->_debug_handler = $handler;
277 } 297 }
278 298
279 /** 299 /**
300 * Sets the Kerberos service principal for use with GSSAPI
301 * authentication.
302 *
303 * @param string $principal The Kerberos service principal
304 *
305 * @return void
306 */
307 function setServicePrincipal($principal)
308 {
309 $this->_gssapiPrincipal = $principal;
310 }
311
312 /**
313 * Sets the Kerberos service CName for use with GSSAPI
314 * authentication.
315 *
316 * @param string $cname The Kerberos service principal
317 *
318 * @return void
319 */
320 function setServiceCN($cname)
321 {
322 $this->_gssapiCN = $cname;
323 }
324
325 /**
280 * Connects to the server and logs in. 326 * Connects to the server and logs in.
281 * 327 *
282 * @return boolean True on success, PEAR_Error on failure. 328 * @return boolean True on success, PEAR_Error on failure.
283 */ 329 */
284 function _handleConnectAndLogin() 330 function _handleConnectAndLogin()
326 return $res; 372 return $res;
327 } 373 }
328 374
329 if ($this->_bypassAuth) { 375 if ($this->_bypassAuth) {
330 $this->_state = NET_SIEVE_STATE_TRANSACTION; 376 $this->_state = NET_SIEVE_STATE_TRANSACTION;
377
378 // Reset capabilities
379 $this->_parseCapability('');
331 } else { 380 } else {
332 $this->_state = NET_SIEVE_STATE_AUTHORISATION; 381 $this->_state = NET_SIEVE_STATE_AUTHORISATION;
382
333 $res = $this->_doCmd(); 383 $res = $this->_doCmd();
334 if (is_a($res, 'PEAR_Error')) { 384 if (is_a($res, 'PEAR_Error')) {
335 return $res; 385 return $res;
336 } 386 }
337 } 387
338 388 // Reset capabilities (use unattended capabilities)
339 // Explicitly ask for the capabilities in case the connection is 389 $this->_parseCapability($res);
340 // picked up from an existing connection. 390 }
341 $res = $this->_cmdCapability(); 391
342 if (is_a($res, 'PEAR_Error')) { 392 // Explicitly ask for the capabilities if needed
343 return $this->_pear->raiseError( 393 if (empty($this->_capability['implementation'])) {
344 'Failed to connect, server said: ' . $res->getMessage(), 2 394 $res = $this->_cmdCapability();
345 ); 395 if (is_a($res, 'PEAR_Error')) {
396 return $this->_pear->raiseError(
397 'Failed to connect, server said: ' . $res->getMessage(), 2
398 );
399 }
346 } 400 }
347 401
348 // Check if we can enable TLS via STARTTLS. 402 // Check if we can enable TLS via STARTTLS.
349 if ($useTLS && !empty($this->_capability['starttls']) 403 if ($useTLS && !empty($this->_capability['starttls'])
350 && function_exists('stream_socket_enable_crypto') 404 && function_exists('stream_socket_enable_crypto')
398 $res = $this->_cmdAuthenticate($user, $pass, $logintype, $euser); 452 $res = $this->_cmdAuthenticate($user, $pass, $logintype, $euser);
399 if (is_a($res, 'PEAR_Error')) { 453 if (is_a($res, 'PEAR_Error')) {
400 return $res; 454 return $res;
401 } 455 }
402 } 456 }
457
403 $this->_state = NET_SIEVE_STATE_TRANSACTION; 458 $this->_state = NET_SIEVE_STATE_TRANSACTION;
404 459
405 return true; 460 return true;
406 } 461 }
407 462
408 /** 463 /**
409 * Returns an indexed array of scripts currently on the server. 464 * Returns an indexed array of scripts currently on the server.
410 * 465 *
411 * @return array Indexed array of scriptnames. 466 * @param string $active Will be set to the name of the active script
412 */ 467 *
413 function listScripts() 468 * @return array Indexed array of scriptnames, PEAR_Error on failure
469 */
470 function listScripts(&$active = null)
414 { 471 {
415 if (is_array($scripts = $this->_cmdListScripts())) { 472 if (is_array($scripts = $this->_cmdListScripts())) {
473 if (isset($scripts[1])) {
474 $active = $scripts[1];
475 }
476
416 return $scripts[0]; 477 return $scripts[0];
417 } else { 478 }
418 return $scripts; 479
419 } 480 return $scripts;
420 } 481 }
421 482
422 /** 483 /**
423 * Returns the active script. 484 * Returns the active script.
424 * 485 *
468 { 529 {
469 $res = $this->_cmdPutScript($scriptname, $script); 530 $res = $this->_cmdPutScript($scriptname, $script);
470 if (is_a($res, 'PEAR_Error')) { 531 if (is_a($res, 'PEAR_Error')) {
471 return $res; 532 return $res;
472 } 533 }
534
473 if ($makeactive) { 535 if ($makeactive) {
474 return $this->_cmdSetActive($scriptname); 536 return $this->_cmdSetActive($scriptname);
475 } 537 }
538
476 return true; 539 return true;
477 } 540 }
478 541
479 /** 542 /**
480 * Removes a script from the server. 543 * Removes a script from the server.
506 569
507 $res = $this->_doCmd(sprintf('HAVESPACE %s %d', $this->_escape($scriptname), $size)); 570 $res = $this->_doCmd(sprintf('HAVESPACE %s %d', $this->_escape($scriptname), $size));
508 if (is_a($res, 'PEAR_Error')) { 571 if (is_a($res, 'PEAR_Error')) {
509 return $res; 572 return $res;
510 } 573 }
574
511 return true; 575 return true;
512 } 576 }
513 577
514 /** 578 /**
515 * Returns the list of extensions the server supports. 579 * Returns the list of extensions the server supports.
519 function getExtensions() 583 function getExtensions()
520 { 584 {
521 if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { 585 if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
522 return $this->_pear->raiseError('Not currently connected', 7); 586 return $this->_pear->raiseError('Not currently connected', 7);
523 } 587 }
588
524 return $this->_capability['extensions']; 589 return $this->_capability['extensions'];
525 } 590 }
526 591
527 /** 592 /**
528 * Returns whether the server supports an extension. 593 * Returns whether the server supports an extension.
558 function getAuthMechs() 623 function getAuthMechs()
559 { 624 {
560 if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { 625 if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
561 return $this->_pear->raiseError('Not currently connected', 7); 626 return $this->_pear->raiseError('Not currently connected', 7);
562 } 627 }
628
563 return $this->_capability['sasl']; 629 return $this->_capability['sasl'];
564 } 630 }
565 631
566 /** 632 /**
567 * Returns whether the server supports an authentication method. 633 * Returns whether the server supports an authentication method.
576 if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) { 642 if (NET_SIEVE_STATE_DISCONNECTED == $this->_state) {
577 return $this->_pear->raiseError('Not currently connected', 7); 643 return $this->_pear->raiseError('Not currently connected', 7);
578 } 644 }
579 645
580 $method = trim($this->_toUpper($method)); 646 $method = trim($this->_toUpper($method));
647
581 if (is_array($this->_capability['sasl'])) { 648 if (is_array($this->_capability['sasl'])) {
582 foreach ($this->_capability['sasl'] as $sasl) { 649 foreach ($this->_capability['sasl'] as $sasl) {
583 if ($sasl == $method) { 650 if ($sasl == $method) {
584 return true; 651 return true;
585 } 652 }
604 { 671 {
605 $method = $this->_getBestAuthMethod($userMethod); 672 $method = $this->_getBestAuthMethod($userMethod);
606 if (is_a($method, 'PEAR_Error')) { 673 if (is_a($method, 'PEAR_Error')) {
607 return $method; 674 return $method;
608 } 675 }
676
609 switch ($method) { 677 switch ($method) {
610 case 'DIGEST-MD5': 678 case 'DIGEST-MD5':
611 return $this->_authDigestMD5($uid, $pwd, $euser); 679 return $this->_authDigestMD5($uid, $pwd, $euser);
612 case 'CRAM-MD5': 680 case 'CRAM-MD5':
613 $result = $this->_authCRAMMD5($uid, $pwd, $euser); 681 $result = $this->_authCRAMMD5($uid, $pwd, $euser);
619 $result = $this->_authPLAIN($uid, $pwd, $euser); 687 $result = $this->_authPLAIN($uid, $pwd, $euser);
620 break; 688 break;
621 case 'EXTERNAL': 689 case 'EXTERNAL':
622 $result = $this->_authEXTERNAL($uid, $pwd, $euser); 690 $result = $this->_authEXTERNAL($uid, $pwd, $euser);
623 break; 691 break;
692 case 'GSSAPI':
693 $result = $this->_authGSSAPI($pwd);
694 break;
624 default : 695 default :
625 $result = $this->_pear->raiseError( 696 $result = $this->_pear->raiseError(
626 $method . ' is not a supported authentication method' 697 $method . ' is not a supported authentication method'
627 ); 698 );
628 break; 699 break;
631 $res = $this->_doCmd(); 702 $res = $this->_doCmd();
632 if (is_a($res, 'PEAR_Error')) { 703 if (is_a($res, 'PEAR_Error')) {
633 return $res; 704 return $res;
634 } 705 }
635 706
636 // Query the server capabilities again now that we are authenticated.
637 if ($this->_pear->isError($res = $this->_cmdCapability())) { 707 if ($this->_pear->isError($res = $this->_cmdCapability())) {
638 return $this->_pear->raiseError( 708 return $this->_pear->raiseError(
639 'Failed to connect, server said: ' . $res->getMessage(), 2 709 'Failed to connect, server said: ' . $res->getMessage(), 2
640 ); 710 );
641 } 711 }
661 ) 731 )
662 ); 732 );
663 } 733 }
664 734
665 /** 735 /**
736 * Authenticates the user using the GSSAPI method.
737 *
738 * @note the PHP krb5 extension is required and the service principal and cname
739 * must have been set.
740 * @see setServicePrincipal()
741 *
742 * @return void
743 */
744 function _authGSSAPI()
745 {
746 if (!extension_loaded('krb5')) {
747 return $this->_pear->raiseError('The krb5 extension is required for GSSAPI authentication', 2);
748 }
749
750 if (!$this->_gssapiPrincipal) {
751 return $this->_pear->raiseError('No Kerberos service principal set', 2);
752 }
753
754 if (!$this->_gssapiCN) {
755 return $this->_pear->raiseError('No Kerberos service CName set', 2);
756 }
757
758 putenv('KRB5CCNAME=' . $this->_gssapiCN);
759
760 try {
761 $ccache = new KRB5CCache();
762 $ccache->open($this->_gssapiCN);
763
764 $gssapicontext = new GSSAPIContext();
765 $gssapicontext->acquireCredentials($ccache);
766
767 $token = '';
768 $success = $gssapicontext->initSecContext($this->_gssapiPrincipal, null, null, null, $token);
769 $token = base64_encode($token);
770 }
771 catch (Exception $e) {
772 return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage());
773 }
774
775 $this->_sendCmd("AUTHENTICATE \"GSSAPI\" {" . strlen($token) . "+}");
776
777 $response = $this->_doCmd($token, true);
778
779 try {
780 $challenge = base64_decode(substr($response, 1, -1));
781 $gssapicontext->unwrap($challenge, $challenge);
782 $gssapicontext->wrap($challenge, $challenge, true);
783 }
784 catch (Exception $e) {
785 return $this->_pear->raiseError('GSSAPI authentication failed: ' . $e->getMessage());
786 }
787
788 $response = base64_encode($challenge);
789
790 $this->_sendCmd("{" . strlen($response) . "+}");
791
792 return $this->_sendCmd($response);
793 }
794
795 /**
666 * Authenticates the user using the LOGIN method. 796 * Authenticates the user using the LOGIN method.
667 * 797 *
668 * @param string $user The userid to authenticate as. 798 * @param string $user The userid to authenticate as.
669 * @param string $pass The password to authenticate with. 799 * @param string $pass The password to authenticate with.
670 * @param string $euser The effective uid to authenticate as. Not used. 800 * @param string $euser The effective uid to authenticate as. Not used.
675 { 805 {
676 $result = $this->_sendCmd('AUTHENTICATE "LOGIN"'); 806 $result = $this->_sendCmd('AUTHENTICATE "LOGIN"');
677 if (is_a($result, 'PEAR_Error')) { 807 if (is_a($result, 'PEAR_Error')) {
678 return $result; 808 return $result;
679 } 809 }
810
680 $result = $this->_doCmd('"' . base64_encode($user) . '"', true); 811 $result = $this->_doCmd('"' . base64_encode($user) . '"', true);
681 if (is_a($result, 'PEAR_Error')) { 812 if (is_a($result, 'PEAR_Error')) {
682 return $result; 813 return $result;
683 } 814 }
815
684 return $this->_doCmd('"' . base64_encode($pass) . '"', true); 816 return $this->_doCmd('"' . base64_encode($pass) . '"', true);
685 } 817 }
686 818
687 /** 819 /**
688 * Authenticates the user using the CRAM-MD5 method. 820 * Authenticates the user using the CRAM-MD5 method.
740 872
741 $result = $this->_sendStringResponse(base64_encode($response)); 873 $result = $this->_sendStringResponse(base64_encode($response));
742 if (is_a($result, 'PEAR_Error')) { 874 if (is_a($result, 'PEAR_Error')) {
743 return $result; 875 return $result;
744 } 876 }
877
745 $result = $this->_doCmd('', true); 878 $result = $this->_doCmd('', true);
746 if (is_a($result, 'PEAR_Error')) { 879 if (is_a($result, 'PEAR_Error')) {
747 return $result; 880 return $result;
748 } 881 }
882
749 if ($this->_toUpper(substr($result, 0, 2)) == 'OK') { 883 if ($this->_toUpper(substr($result, 0, 2)) == 'OK') {
750 return; 884 return;
751 } 885 }
752 886
753 /* We don't use the protocol's third step because SIEVE doesn't allow 887 /* We don't use the protocol's third step because SIEVE doesn't allow
767 * @param string $pass The password to authenticate with. 901 * @param string $pass The password to authenticate with.
768 * @param string $euser The effective uid to authenticate as. 902 * @param string $euser The effective uid to authenticate as.
769 * 903 *
770 * @return void 904 * @return void
771 * 905 *
772 * @since 1.1.7 906 * @since 1.1.7
773 */ 907 */
774 function _authEXTERNAL($user, $pass, $euser) 908 function _authEXTERNAL($user, $pass, $euser)
775 { 909 {
776 $cmd = sprintf( 910 $cmd = sprintf(
777 'AUTHENTICATE "EXTERNAL" "%s"', 911 'AUTHENTICATE "EXTERNAL" "%s"',
778 base64_encode(strlen($euser) ? $euser : $user) 912 base64_encode(strlen($euser) ? $euser : $user)
779 ); 913 );
914
780 return $this->_sendCmd($cmd); 915 return $this->_sendCmd($cmd);
781 } 916 }
782 917
783 /** 918 /**
784 * Removes a script from the server. 919 * Removes a script from the server.
795 930
796 $res = $this->_doCmd(sprintf('DELETESCRIPT %s', $this->_escape($scriptname))); 931 $res = $this->_doCmd(sprintf('DELETESCRIPT %s', $this->_escape($scriptname)));
797 if (is_a($res, 'PEAR_Error')) { 932 if (is_a($res, 'PEAR_Error')) {
798 return $res; 933 return $res;
799 } 934 }
935
800 return true; 936 return true;
801 } 937 }
802 938
803 /** 939 /**
804 * Retrieves the contents of the named script. 940 * Retrieves the contents of the named script.
976 case 'IMPLEMENTATION': 1112 case 'IMPLEMENTATION':
977 $this->_capability['implementation'] = $matches[3]; 1113 $this->_capability['implementation'] = $matches[3];
978 break; 1114 break;
979 1115
980 case 'SASL': 1116 case 'SASL':
981 $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]); 1117 if (!empty($matches[3])) {
1118 $this->_capability['sasl'] = preg_split('/\s+/', $matches[3]);
1119 }
982 break; 1120 break;
983 1121
984 case 'SIEVE': 1122 case 'SIEVE':
985 $this->_capability['extensions'] = preg_split('/\s+/', $matches[3]); 1123 if (!empty($matches[3])) {
1124 $this->_capability['extensions'] = preg_split('/\s+/', $matches[3]);
1125 }
986 break; 1126 break;
987 1127
988 case 'STARTTLS': 1128 case 'STARTTLS':
989 $this->_capability['starttls'] = true; 1129 $this->_capability['starttls'] = true;
990 break; 1130 break;
1225 return $res; 1365 return $res;
1226 } 1366 }
1227 1367
1228 if (isset($this->_options['ssl']['crypto_method'])) { 1368 if (isset($this->_options['ssl']['crypto_method'])) {
1229 $crypto_method = $this->_options['ssl']['crypto_method']; 1369 $crypto_method = $this->_options['ssl']['crypto_method'];
1230 } 1370 } else {
1231 else {
1232 // There is no flag to enable all TLS methods. Net_SMTP 1371 // There is no flag to enable all TLS methods. Net_SMTP
1233 // handles enabling TLS similarly. 1372 // handles enabling TLS similarly.
1234 $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT 1373 $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT
1235 | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT 1374 | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
1236 | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; 1375 | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
1248 // CAPABILITY response, thus we would wait here forever. Parse the 1387 // CAPABILITY response, thus we would wait here forever. Parse the
1249 // Cyrus version and work around this broken behavior. 1388 // Cyrus version and work around this broken behavior.
1250 if (!preg_match('/^CYRUS TIMSIEVED V([0-9.]+)/', $this->_capability['implementation'], $matches) 1389 if (!preg_match('/^CYRUS TIMSIEVED V([0-9.]+)/', $this->_capability['implementation'], $matches)
1251 || version_compare($matches[1], '2.3.10', '>=') 1390 || version_compare($matches[1], '2.3.10', '>=')
1252 ) { 1391 ) {
1253 $this->_doCmd(); 1392 $res = $this->_doCmd();
1254 } 1393 }
1255 1394
1256 // Query the server capabilities again now that we are under 1395 // Reset capabilities (use unattended capabilities)
1257 // encryption. 1396 $this->_parseCapability(is_string($res) ? $res : '');
1258 $res = $this->_cmdCapability(); 1397
1259 if (is_a($res, 'PEAR_Error')) { 1398 // Query the server capabilities again now that we are under encryption.
1260 return $this->_pear->raiseError( 1399 if (empty($this->_capability['implementation'])) {
1261 'Failed to connect, server said: ' . $res->getMessage(), 2 1400 $res = $this->_cmdCapability();
1262 ); 1401 if (is_a($res, 'PEAR_Error')) {
1402 return $this->_pear->raiseError(
1403 'Failed to connect, server said: ' . $res->getMessage(), 2
1404 );
1405 }
1263 } 1406 }
1264 1407
1265 return true; 1408 return true;
1266 } 1409 }
1267 1410
1273 * @return integer The length of the string. 1416 * @return integer The length of the string.
1274 */ 1417 */
1275 function _getLineLength($string) 1418 function _getLineLength($string)
1276 { 1419 {
1277 if (extension_loaded('mbstring')) { 1420 if (extension_loaded('mbstring')) {
1278 return mb_strlen($string, 'latin1'); 1421 return mb_strlen($string, '8bit');
1279 } else { 1422 } else {
1280 return strlen($string); 1423 return strlen($string);
1281 } 1424 }
1282 } 1425 }
1283 1426