Added "Allow self signed certificates" setting

Updated recaptcha plugin
This commit is contained in:
RainLoop Team 2015-01-06 01:41:22 +04:00
parent 46187d0749
commit 833f40c115
35 changed files with 363 additions and 273 deletions

View file

@ -29,6 +29,7 @@
this.capaTwoFactorAuth = ko.observable(Settings.capa(Enums.Capa.TwoFactor));
this.verifySslCertificate = ko.observable(!!Settings.settingsGet('VerifySslCertificate'));
this.allowSelfSigned = ko.observable(!!Settings.settingsGet('AllowSelfSigned'));
this.adminLogin = ko.observable(Settings.settingsGet('AdminLogin'));
this.adminLoginError = ko.observable(false);
@ -138,6 +139,12 @@
'VerifySslCertificate': bValue ? '1' : '0'
});
});
this.allowSelfSigned.subscribe(function (bValue) {
Remote.saveAdminConfig(null, {
'AllowSelfSigned': bValue ? '1' : '0'
});
});
};
SecurityAdminSettings.prototype.onHide = function ()

View file

@ -60,6 +60,9 @@
.e-component.material-design {
margin-top: 2px;
margin-bottom: 6px;
&.e-checkbox {
.sub-checkbox-container {

View file

@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2013 RainLoop Team
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,3 @@
A CAPTCHA is a program that can generate and grade tests that humans can pass but current computer programs cannot.
For example, humans can read distorted text as the one shown below, but current computer programs can't.
More info at http://www.google.com/recaptcha

View file

@ -0,0 +1 @@
1.9

View file

@ -1,6 +1,6 @@
<?php
class Recaptcha2Plugin extends \RainLoop\Plugins\AbstractPlugin
class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
{
/**
* @return void
@ -24,15 +24,11 @@ class Recaptcha2Plugin extends \RainLoop\Plugins\AbstractPlugin
public function configMapping()
{
return array(
\RainLoop\Plugins\Property::NewInstance('public_key')->SetLabel('Site key')
\RainLoop\Plugins\Property::NewInstance('public_key')->SetLabel('Public Key')
->SetAllowedInJs(true)
->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('private_key')->SetLabel('Secret key')
\RainLoop\Plugins\Property::NewInstance('private_key')->SetLabel('Private Key')
->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('theme')->SetLabel('Theme')
->SetAllowedInJs(true)
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array('light', 'dark')),
\RainLoop\Plugins\Property::NewInstance('error_limit')->SetLabel('Limit')
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array(0, 1, 2, 3, 4, 5))
@ -45,7 +41,7 @@ class Recaptcha2Plugin extends \RainLoop\Plugins\AbstractPlugin
*/
private function getCaptchaCacherKey()
{
return 'Captcha2/Login/'.\RainLoop\Utils::GetConnectionToken();
return 'Captcha/Login/'.\RainLoop\Utils::GetConnectionToken();
}
/**
@ -59,7 +55,7 @@ class Recaptcha2Plugin extends \RainLoop\Plugins\AbstractPlugin
$oCacher = $this->Manager()->Actions()->Cacher();
$sLimit = $oCacher && $oCacher->IsInited() ? $oCacher->Get($this->getCaptchaCacherKey()) : '0';
if (0 < \strlen($sLimit) && \is_numeric($sLimit))
if (0 < strlen($sLimit) && is_numeric($sLimit))
{
$iConfigLimit -= (int) $sLimit;
}
@ -73,7 +69,7 @@ class Recaptcha2Plugin extends \RainLoop\Plugins\AbstractPlugin
*/
public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aData)
{
if (!$bAdmin && !$bAuth && \is_array($aData))
if (!$bAdmin && !$bAuth && is_array($aData))
{
$aData['show_captcha_on_login'] = 1 > $this->getLimit();
}
@ -86,25 +82,18 @@ class Recaptcha2Plugin extends \RainLoop\Plugins\AbstractPlugin
{
if ('Login' === $sAction && 0 >= $this->getLimit())
{
$bResult = false;
require_once __DIR__.'/recaptchalib.php';
$sResult = $this->Manager()->Actions()->Http()->GetUrlAsString(
'https://www.google.com/recaptcha/api/siteverify?secret='.
\urlencode($this->Config()->Get('plugin', 'private_key', '')).'&response='.
\urlencode($this->Manager()->Actions()->GetActionParam('RecaptchaResponse', '')));
$oResp = recaptcha_check_answer(
$this->Config()->Get('plugin', 'private_key', ''),
isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
$this->Manager()->Actions()->GetActionParam('RecaptchaChallenge', ''),
$this->Manager()->Actions()->GetActionParam('RecaptchaResponse', '')
);
if ($sResult)
if (!$oResp || !isset($oResp->is_valid) || !$oResp->is_valid)
{
$aResp = @\json_decode($sResult, true);
if (\is_array($aResp) && isset($aResp['success']) && $aResp['success'])
{
$bResult = true;
}
}
if (!$bResult)
{
$this->Manager()->Actions()->Logger()->Write('RecaptchaResponse:'.$sResult);
$this->Manager()->Actions()->Logger()->WriteDump($oResp);
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CaptchaError);
}
}
@ -128,7 +117,7 @@ class Recaptcha2Plugin extends \RainLoop\Plugins\AbstractPlugin
{
$iLimit = 0;
$sLimut = $oCacher->Get($sKey);
if (0 < \strlen($sLimut) && \is_numeric($sLimut))
if (0 < strlen($sLimut) && is_numeric($sLimut))
{
$iLimit = (int) $sLimut;
}

View file

@ -0,0 +1,78 @@
$(function () {
var
bStarted = false,
bShown = false
;
function ShowRecaptcha()
{
if (window.Recaptcha)
{
if (bShown)
{
window.Recaptcha.reload();
}
else
{
window.Recaptcha.create(window.rl.pluginSettingsGet('recaptcha', 'public_key'), 'recaptcha-place', {
'theme': 'custom',
'lang': window.rl.settingsGet('Language')
});
}
bShown = true;
}
}
function StartRecaptcha()
{
if (!window.Recaptcha)
{
$.getScript('//www.google.com/recaptcha/api/js/recaptcha_ajax.js', ShowRecaptcha);
}
else
{
ShowRecaptcha();
}
}
if (window.rl)
{
window.rl.addHook('view-model-on-show', function (sName, oViewModel) {
if (!bStarted && oViewModel &&
('View:RainLoop:Login' === sName || 'View/App/Login' === sName || 'LoginViewModel' === sName || 'LoginAppView' === sName) &&
window.rl.pluginSettingsGet('recaptcha', 'show_captcha_on_login'))
{
bStarted = true;
StartRecaptcha();
}
});
window.rl.addHook('ajax-default-request', function (sAction, oParameters) {
if ('Login' === sAction && oParameters && bShown && window.Recaptcha)
{
oParameters['RecaptchaChallenge'] = window.Recaptcha.get_challenge();
oParameters['RecaptchaResponse'] = window.Recaptcha.get_response();
}
});
window.rl.addHook('ajax-default-response', function (sAction, oData, sType) {
if ('Login' === sAction)
{
if (!oData || 'success' !== sType || !oData['Result'])
{
if (bShown && window.Recaptcha)
{
window.Recaptcha.reload();
}
else if (oData && oData['Captcha'])
{
StartRecaptcha();
}
}
}
});
}
});

View file

@ -0,0 +1,14 @@
<div class="recaptcha-control-group" id="recaptcha-place" style="display: none">
<div class="controls">
<div id="recaptcha_image" style="border-radius: 3px"></div>
</div>
<div class="controls">
<div class="input-append">
<input class="i18n input-block-level inputLoginForm inputCAPTCHA" type="text" autocomplete="off"
id="recaptcha_response_field" data-i18n-placeholder="PLUGIN/LABEL_ENTER_THE_WORDS_ABOVE" />
<span class="add-on">
<i class="icon-repeat" onclick="Recaptcha.reload()" style="cursor: pointer"></i>
</span>
</div>
</div>
</div>

View file

@ -1,83 +0,0 @@
$(function () {
var
nId = null,
bStarted = false
;
function ShowRecaptcha()
{
if (window.grecaptcha)
{
if (null === nId)
{
$('#recaptcha-place').show();
nId = window.grecaptcha.render('recaptcha-div', {
'sitekey': window.rl.pluginSettingsGet('recaptcha-2', 'public_key'),
'theme': window.rl.pluginSettingsGet('recaptcha-2', 'theme')
});
}
}
}
window.__globalShowRecaptcha = ShowRecaptcha;
function StartRecaptcha()
{
if (!window.grecaptcha && window.rl)
{
$.getScript('https://www.google.com/recaptcha/api.js?onload=__globalShowRecaptcha&render=explicit&hl=' + window.rl.settingsGet('Language'));
}
else
{
ShowRecaptcha();
}
}
if (window.rl)
{
window.rl.addHook('user-login-submit', function (fSubmitResult) {
if (null !== nId && !window.grecaptcha.getResponse(nId))
{
fSubmitResult(105);
}
});
window.rl.addHook('view-model-on-show', function (sName, oViewModel) {
if (!bStarted && oViewModel &&
('View:RainLoop:Login' === sName || 'View/App/Login' === sName || 'LoginViewModel' === sName || 'LoginAppView' === sName) &&
window.rl.pluginSettingsGet('recaptcha-2', 'show_captcha_on_login'))
{
bStarted = true;
StartRecaptcha();
}
});
window.rl.addHook('ajax-default-request', function (sAction, oParameters) {
if ('Login' === sAction && oParameters && null !== nId && window.grecaptcha)
{
oParameters['RecaptchaResponse'] = window.grecaptcha.getResponse(nId);
}
});
window.rl.addHook('ajax-default-response', function (sAction, oData, sType) {
if ('Login' === sAction)
{
if (!oData || 'success' !== sType || !oData['Result'])
{
if (null !== nId && window.grecaptcha)
{
window.grecaptcha.reset(nId);
}
else if (oData && oData['Captcha'])
{
StartRecaptcha();
}
}
}
});
}
});

View file

@ -1,3 +0,0 @@
<div class="controls recaptcha-control-group" id="recaptcha-place" style="display: none;">
<center id="recaptcha-div"></center>
</div>

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2013 RainLoop Team
Copyright (c) 2015 RainLoop Team
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View file

@ -1,3 +1,3 @@
A CAPTCHA is a program that can generate and grade tests that humans can pass but current computer programs cannot.
A CAPTCHA (v2) is a program that can generate and grade tests that humans can pass but current computer programs cannot.
For example, humans can read distorted text as the one shown below, but current computer programs can't.
More info at http://www.google.com/recaptcha

View file

@ -1 +1 @@
1.9
2.0

View file

@ -24,11 +24,15 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
public function configMapping()
{
return array(
\RainLoop\Plugins\Property::NewInstance('public_key')->SetLabel('Public Key')
\RainLoop\Plugins\Property::NewInstance('public_key')->SetLabel('Site key')
->SetAllowedInJs(true)
->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('private_key')->SetLabel('Private Key')
\RainLoop\Plugins\Property::NewInstance('private_key')->SetLabel('Secret key')
->SetDefaultValue(''),
\RainLoop\Plugins\Property::NewInstance('theme')->SetLabel('Theme')
->SetAllowedInJs(true)
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array('light', 'dark')),
\RainLoop\Plugins\Property::NewInstance('error_limit')->SetLabel('Limit')
->SetType(\RainLoop\Enumerations\PluginPropertyType::SELECTION)
->SetDefaultValue(array(0, 1, 2, 3, 4, 5))
@ -41,7 +45,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
*/
private function getCaptchaCacherKey()
{
return 'Captcha/Login/'.\RainLoop\Utils::GetConnectionToken();
return 'CaptchaNew/Login/'.\RainLoop\Utils::GetConnectionToken();
}
/**
@ -55,7 +59,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
$oCacher = $this->Manager()->Actions()->Cacher();
$sLimit = $oCacher && $oCacher->IsInited() ? $oCacher->Get($this->getCaptchaCacherKey()) : '0';
if (0 < strlen($sLimit) && is_numeric($sLimit))
if (0 < \strlen($sLimit) && \is_numeric($sLimit))
{
$iConfigLimit -= (int) $sLimit;
}
@ -69,7 +73,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
*/
public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aData)
{
if (!$bAdmin && !$bAuth && is_array($aData))
if (!$bAdmin && !$bAuth && \is_array($aData))
{
$aData['show_captcha_on_login'] = 1 > $this->getLimit();
}
@ -82,18 +86,25 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
{
if ('Login' === $sAction && 0 >= $this->getLimit())
{
require_once __DIR__.'/recaptchalib.php';
$bResult = false;
$oResp = recaptcha_check_answer(
$this->Config()->Get('plugin', 'private_key', ''),
isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '',
$this->Manager()->Actions()->GetActionParam('RecaptchaChallenge', ''),
$this->Manager()->Actions()->GetActionParam('RecaptchaResponse', '')
);
$sResult = $this->Manager()->Actions()->Http()->GetUrlAsString(
'https://www.google.com/recaptcha/api/siteverify?secret='.
\urlencode($this->Config()->Get('plugin', 'private_key', '')).'&response='.
\urlencode($this->Manager()->Actions()->GetActionParam('RecaptchaResponse', '')));
if (!$oResp || !isset($oResp->is_valid) || !$oResp->is_valid)
if ($sResult)
{
$this->Manager()->Actions()->Logger()->WriteDump($oResp);
$aResp = @\json_decode($sResult, true);
if (\is_array($aResp) && isset($aResp['success']) && $aResp['success'])
{
$bResult = true;
}
}
if (!$bResult)
{
$this->Manager()->Actions()->Logger()->Write('RecaptchaResponse:'.$sResult);
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CaptchaError);
}
}
@ -109,6 +120,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
{
$oCacher = $this->Manager()->Actions()->Cacher();
$iConfigLimit = (int) $this->Config()->Get('plugin', 'error_limit', 0);
$sKey = $this->getCaptchaCacherKey();
if (0 < $iConfigLimit && $oCacher && $oCacher->IsInited())
@ -117,7 +129,7 @@ class RecaptchaPlugin extends \RainLoop\Plugins\AbstractPlugin
{
$iLimit = 0;
$sLimut = $oCacher->Get($sKey);
if (0 < strlen($sLimut) && is_numeric($sLimut))
if (0 < \strlen($sLimut) && \is_numeric($sLimut))
{
$iLimit = (int) $sLimut;
}

View file

@ -1,78 +1,89 @@
(function ($, window) {
$(function () {
$(function () {
var
bStarted = false,
bShown = false
;
var
nId = null,
bStarted = false
;
function ShowRecaptcha()
{
if (window.Recaptcha)
function ShowRecaptcha()
{
if (bShown)
if (window.grecaptcha)
{
window.Recaptcha.reload();
}
else
{
window.Recaptcha.create(window.rl.pluginSettingsGet('recaptcha', 'public_key'), 'recaptcha-place', {
'theme': 'custom',
'lang': window.rl.settingsGet('Language')
});
}
bShown = true;
}
}
function StartRecaptcha()
{
if (!window.Recaptcha)
{
$.getScript('//www.google.com/recaptcha/api/js/recaptcha_ajax.js', ShowRecaptcha);
}
else
{
ShowRecaptcha();
}
}
if (window.rl)
{
window.rl.addHook('view-model-on-show', function (sName, oViewModel) {
if (!bStarted && oViewModel &&
('View:RainLoop:Login' === sName || 'View/App/Login' === sName || 'LoginViewModel' === sName || 'LoginAppView' === sName) &&
window.rl.pluginSettingsGet('recaptcha', 'show_captcha_on_login'))
{
bStarted = true;
StartRecaptcha();
}
});
window.rl.addHook('ajax-default-request', function (sAction, oParameters) {
if ('Login' === sAction && oParameters && bShown && window.Recaptcha)
{
oParameters['RecaptchaChallenge'] = window.Recaptcha.get_challenge();
oParameters['RecaptchaResponse'] = window.Recaptcha.get_response();
}
});
window.rl.addHook('ajax-default-response', function (sAction, oData, sType) {
if ('Login' === sAction)
{
if (!oData || 'success' !== sType || !oData['Result'])
if (null === nId)
{
if (bShown && window.Recaptcha)
var oEl = $('#recaptcha-div');
if (oEl && oEl[0])
{
window.Recaptcha.reload();
}
else if (oData && oData['Captcha'])
{
StartRecaptcha();
oEl.show();
nId = window.grecaptcha.render(oEl[0], {
'sitekey': window.rl.pluginSettingsGet('recaptcha', 'public_key'),
'theme': window.rl.pluginSettingsGet('recaptcha', 'theme')
});
}
}
}
});
}
});
}
window.__globalShowRecaptcha = ShowRecaptcha;
function StartRecaptcha()
{
if (!window.grecaptcha && window.rl)
{
$.getScript('https://www.google.com/recaptcha/api.js?onload=__globalShowRecaptcha&render=explicit&hl=' + window.rl.settingsGet('Language'));
}
else
{
ShowRecaptcha();
}
}
if (window.rl)
{
window.rl.addHook('user-login-submit', function (fSubmitResult) {
if (null !== nId && !window.grecaptcha.getResponse(nId))
{
fSubmitResult(105);
}
});
window.rl.addHook('view-model-on-show', function (sName, oViewModel) {
if (!bStarted && oViewModel &&
('View:RainLoop:Login' === sName || 'View/App/Login' === sName || 'LoginViewModel' === sName || 'LoginAppView' === sName) &&
window.rl.pluginSettingsGet('recaptcha', 'show_captcha_on_login'))
{
bStarted = true;
StartRecaptcha();
}
});
window.rl.addHook('ajax-default-request', function (sAction, oParameters) {
if ('Login' === sAction && oParameters && null !== nId && window.grecaptcha)
{
oParameters['RecaptchaResponse'] = window.grecaptcha.getResponse(nId);
}
});
window.rl.addHook('ajax-default-response', function (sAction, oData, sType) {
if ('Login' === sAction)
{
if (!oData || 'success' !== sType || !oData['Result'])
{
if (null !== nId && window.grecaptcha)
{
window.grecaptcha.reset(nId);
}
else if (oData && oData['Captcha'])
{
StartRecaptcha();
}
}
}
});
}
});
}($, window));

View file

@ -1,14 +1 @@
<div class="recaptcha-control-group" id="recaptcha-place" style="display: none">
<div class="controls">
<div id="recaptcha_image" style="border-radius: 3px"></div>
</div>
<div class="controls">
<div class="input-append">
<input class="i18n input-block-level inputLoginForm inputCAPTCHA" type="text" autocomplete="off"
id="recaptcha_response_field" data-i18n-placeholder="PLUGIN/LABEL_ENTER_THE_WORDS_ABOVE" />
<span class="add-on">
<i class="icon-repeat" onclick="Recaptcha.reload()" style="cursor: pointer"></i>
</span>
</div>
</div>
</div>
<div class="controls" id="recaptcha-div" style="display: none"></div>

View file

@ -136,6 +136,7 @@ class ImapClient extends \MailSo\Net\NetClient
* @param int $iPort = 143
* @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT
* @param bool $bVerifySsl = false
* @param bool $bAllowSelfSigned = true
*
* @return \MailSo\Imap\ImapClient
*
@ -144,11 +145,12 @@ class ImapClient extends \MailSo\Net\NetClient
* @throws \MailSo\Imap\Exceptions\Exception
*/
public function Connect($sServerName, $iPort = 143,
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false)
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT,
$bVerifySsl = false, $bAllowSelfSigned = true)
{
$this->aTagTimeouts['*'] = \microtime(true);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned);
$this->parseResponseWithValidation('*', true);

View file

@ -195,6 +195,7 @@ abstract class NetClient
* @param int $iPort
* @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT
* @param bool $bVerifySsl = false
* @param bool $bAllowSelfSigned = true
*
* @return void
*
@ -203,7 +204,8 @@ abstract class NetClient
* @throws \MailSo\Net\Exceptions\SocketCanNotConnectToHostException
*/
public function Connect($sServerName, $iPort,
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false)
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT,
$bVerifySsl = false, $bAllowSelfSigned = true)
{
if (!\MailSo\Base\Validator::NotEmptyString($sServerName, true) || !\MailSo\Base\Validator::PortInt($iPort))
{
@ -251,12 +253,14 @@ abstract class NetClient
// $iErrorNo, $sErrorStr, $this->iConnectTimeOut);
$bVerifySsl = !!$bVerifySsl;
$bAllowSelfSigned = $bVerifySsl ? !!$bAllowSelfSigned : true;
$aStreamContextSettings = array(
'ssl' => array(
'verify_host' => $bVerifySsl,
'verify_peer' => $bVerifySsl,
'verify_peer_name' => $bVerifySsl,
'allow_self_signed' => !$bVerifySsl
'allow_self_signed' => $bAllowSelfSigned
)
);

View file

@ -63,6 +63,7 @@ class Pop3Client extends \MailSo\Net\NetClient
* @param int $iPort = 110
* @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT
* @param bool $bVerifySsl = false
* @param bool $bAllowSelfSigned = null
*
* @return \MailSo\Pop3\Pop3Client
*
@ -71,11 +72,13 @@ class Pop3Client extends \MailSo\Net\NetClient
* @throws \MailSo\Pop3\Exceptions\ResponseException
*/
public function Connect($sServerName, $iPort = 110,
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false)
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT,
$bVerifySsl = false, $bAllowSelfSigned = null)
{
$this->iRequestTime = microtime(true);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned);
$this->validateResponse();
if (\MailSo\Net\Enumerations\ConnectionSecurityType::UseStartTLS(

View file

@ -51,6 +51,7 @@ class PoppassdClient extends \MailSo\Net\NetClient
* @param int $iPort = 106
* @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT
* @param bool $bVerifySsl = false
* @param bool $bAllowSelfSigned = true
*
* @return \MailSo\Poppassd\PoppassdClient
*
@ -59,11 +60,13 @@ class PoppassdClient extends \MailSo\Net\NetClient
* @throws \MailSo\Poppassd\Exceptions\ResponseException
*/
public function Connect($sServerName, $iPort = 106,
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false)
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT,
$bVerifySsl = false, $bAllowSelfSigned = true)
{
$this->iRequestTime = \microtime(true);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned);
$this->validateResponse();
return $this;

View file

@ -88,6 +88,7 @@ class ManageSieveClient extends \MailSo\Net\NetClient
* @param int $iPort
* @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT
* @param bool $bVerifySsl = false
* @param bool $bAllowSelfSigned = true
*
* @return \MailSo\Sieve\ManageSieveClient
*
@ -96,11 +97,12 @@ class ManageSieveClient extends \MailSo\Net\NetClient
* @throws \MailSo\Sieve\Exceptions\ResponseException
*/
public function Connect($sServerName, $iPort,
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false)
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT,
$bVerifySsl = false, $bAllowSelfSigned = true)
{
$this->iRequestTime = microtime(true);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned);
$mResponse = $this->parseResponse();
$this->validateResponse($mResponse);

View file

@ -151,6 +151,7 @@ class SmtpClient extends \MailSo\Net\NetClient
* @param string $sEhloHost = '[127.0.0.1]'
* @param int $iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT
* @param bool $bVerifySsl = false
* @param bool $bAllowSelfSigned = true
*
* @return \MailSo\Smtp\SmtpClient
*
@ -159,11 +160,13 @@ class SmtpClient extends \MailSo\Net\NetClient
* @throws \MailSo\Smtp\Exceptions\ResponseException
*/
public function Connect($sServerName, $iPort = 25, $sEhloHost = '[127.0.0.1]',
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT, $bVerifySsl = false)
$iSecurityType = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT,
$bVerifySsl = false, $bAllowSelfSigned = true)
{
$this->iRequestTime = microtime(true);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl);
parent::Connect($sServerName, $iPort, $iSecurityType, $bVerifySsl, $bAllowSelfSigned);
$this->validateResponse(220);
$this->preLoginStartTLSAndEhloProcess($sEhloHost);

View file

@ -1247,7 +1247,9 @@ class Actions
$aResult['AdminDomain'] = APP_SITE;
$aResult['UseTokenProtection'] = (bool) $oConfig->Get('security', 'csrf_protection', true);
$aResult['EnabledPlugins'] = (bool) $oConfig->Get('plugins', 'enable', false);
$aResult['VerifySslCertificate'] = !!$oConfig->Get('ssl', 'verify_certificate', false);
$aResult['AllowSelfSigned'] = !!$oConfig->Get('ssl', 'allow_self_signed', true);
$aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array();
$aResult['MySqlIsSupported'] = \is_array($aDrivers) ? \in_array('mysql', $aDrivers) : false;
@ -2613,6 +2615,8 @@ class Actions
});
$this->setConfigFromParams($oConfig, 'VerifySslCertificate', 'ssl', 'verify_certificate', 'bool');
$this->setConfigFromParams($oConfig, 'AllowSelfSigned', 'ssl', 'allow_self_signed', 'bool');
$this->setConfigFromParams($oConfig, 'UseLocalProxyForExternalImages', 'labs', 'use_local_proxy_for_external_images', 'bool');
$this->setConfigFromParams($oConfig, 'AllowLanguagesOnSettings', 'webmail', 'allow_languages_on_settings', 'bool');
@ -3100,8 +3104,10 @@ class Actions
$oImapClient->SetTimeOuts($iConnectionTimeout);
$iTime = \microtime(true);
$oImapClient->Connect($oDomain->IncHost(), $oDomain->IncPort(),
$oDomain->IncSecure(), !!$this->Config()->Get('ssl', 'verify_certificate'));
$oImapClient->Connect($oDomain->IncHost(), $oDomain->IncPort(), $oDomain->IncSecure(),
!!$this->Config()->Get('ssl', 'verify_certificate', false),
!!$this->Config()->Get('ssl', 'allow_self_signed', true)
);
$iImapTime = \microtime(true) - $iTime;
$oImapClient->Disconnect();
@ -3139,8 +3145,10 @@ class Actions
$iTime = \microtime(true);
$oSmtpClient->Connect($oDomain->OutHost(), $oDomain->OutPort(),
\MailSo\Smtp\SmtpClient::EhloHelper(),
$oDomain->OutSecure(), !!$this->Config()->Get('ssl', 'verify_certificate'));
\MailSo\Smtp\SmtpClient::EhloHelper(), $oDomain->OutSecure(),
!!$this->Config()->Get('ssl', 'verify_certificate', false),
!!$this->Config()->Get('ssl', 'allow_self_signed', true)
);
$iSmtpTime = \microtime(true) - $iTime;
$oSmtpClient->Disconnect();

View file

@ -122,6 +122,7 @@ class Application extends \RainLoop\Config\AbstractConfig
'ssl' => array(
'verify_certificate' => array(false, 'Require verification of SSL certificate used.'),
'allow_self_signed' => array(true, 'Allow self-signed certificates. Requires verify_certificate.'),
'cafile' => array('', 'Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)'),
'capath' => array('', 'capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)'),
),

View file

@ -346,7 +346,8 @@ class Account extends \RainLoop\Account // for backward compatibility
'Password' => $this->Password(),
'ProxyAuthUser' => $this->ProxyAuthUser(),
'ProxyAuthPassword' => $this->ProxyAuthPassword(),
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate'),
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false),
'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true),
'UseAuthPlainIfSupported' => !!$oConfig->Get('labs', 'use_imap_auth_plain')
);
@ -358,7 +359,8 @@ class Account extends \RainLoop\Account // for backward compatibility
{
$oMailClient
->Connect($aImapCredentials['Host'], $aImapCredentials['Port'],
$aImapCredentials['Secure'], $aImapCredentials['VerifySsl']);
$aImapCredentials['Secure'], $aImapCredentials['VerifySsl'], $aImapCredentials['AllowSelfSigned']);
}
$oPlugins->RunHook('event.imap-pre-login', array($this, $aImapCredentials['UseAuth'], $aImapCredentials));
@ -410,7 +412,8 @@ class Account extends \RainLoop\Account // for backward compatibility
'Password' => $this->Password(),
'ProxyAuthUser' => $this->ProxyAuthUser(),
'ProxyAuthPassword' => $this->ProxyAuthPassword(),
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate')
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false),
'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true)
);
$oPlugins->RunHook('filter.smtp-credentials', array($this, &$aSmtpCredentials));
@ -421,8 +424,9 @@ class Account extends \RainLoop\Account // for backward compatibility
if ($aSmtpCredentials['UseConnect'] && !$aSmtpCredentials['UsePhpMail'] && $oSmtpClient)
{
$oSmtpClient->Connect($aSmtpCredentials['Host'], $aSmtpCredentials['Port'],
$aSmtpCredentials['Ehlo'], $aSmtpCredentials['Secure'], $aSmtpCredentials['VerifySsl']);
$oSmtpClient->Connect($aSmtpCredentials['Host'], $aSmtpCredentials['Port'], $aSmtpCredentials['Ehlo'],
$aSmtpCredentials['Secure'], $aSmtpCredentials['VerifySsl'], $aSmtpCredentials['AllowSelfSigned']
);
}
$oPlugins->RunHook('event.smtp-post-connect', array($this, $aSmtpCredentials['UseConnect'], $aSmtpCredentials));

View file

@ -171,7 +171,9 @@ class Manager
\file_exists($sPathName.'/index.php'))
{
$aList[] = array(
$sName, @\file_get_contents($sPathName.'/VERSION')
$sName,
\file_exists($sPathName.'/VERSION') ?
\file_get_contents($sPathName.'/VERSION') : '0.0'
);
}
}

View file

@ -31,17 +31,36 @@
</div>
<div class="control-group">
<div class="controls">
<div data-bind="component: {
name: 'Checkbox',
params: { value: verifySslCertificate, label: 'Require verification of SSL certificate used (IMAP/SMTP)', inline: true }
}"></div>
&nbsp;&nbsp;
<span style="color:red">(unstable)</span>
<a href="#" target="_blank" class="g-ui-link" data-bind="link: phpInfoLink()">Show PHP information</a>
</div>
</div>
</div>
<div class="form-horizontal">
<div class="legend">
SSL
</div>
<div class="control-group">
<div class="controls">
<a href="#" target="_blank" class="g-ui-link" data-bind="link: phpInfoLink()">Show PHP information</a>
<div data-bind="component: {
name: 'Checkbox',
params: {
value: verifySslCertificate,
label: 'Require verification of SSL certificate used (IMAP/SMTP)',
inline: true
}
}"></div>
&nbsp;&nbsp;
<span style="color:red">(unstable)</span>
<br />
<div data-bind="component: {
name: 'Checkbox',
params: {
enable: verifySslCertificate,
value: allowSelfSigned,
label: 'Allow self signed certificates'
}
}"></div>
</div>
</div>
</div>