Small fixes

This commit is contained in:
RainLoop Team 2014-10-23 21:59:21 +04:00
parent 300cee0b6e
commit 3e9a7a55c6
15 changed files with 405 additions and 292 deletions

View file

@ -21,7 +21,6 @@
; ;
this.capa = !!Settings.settingsGet('PremType'); this.capa = !!Settings.settingsGet('PremType');
this.capa = true;
this.title = ko.observable(Settings.settingsGet('Title')); this.title = ko.observable(Settings.settingsGet('Title'));
this.title.trigger = ko.observable(Enums.SaveSettingsStep.Idle); this.title.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
@ -37,6 +36,8 @@
this.loginCss = ko.observable(Settings.settingsGet('LoginCss')); this.loginCss = ko.observable(Settings.settingsGet('LoginCss'));
this.loginCss.trigger = ko.observable(Enums.SaveSettingsStep.Idle); this.loginCss.trigger = ko.observable(Enums.SaveSettingsStep.Idle);
this.loginPowered = ko.observable(!!Settings.settingsGet('LoginPowered'));
} }
BrandingAdminSetting.prototype.onBuild = function () BrandingAdminSetting.prototype.onBuild = function ()
@ -46,30 +47,37 @@
Remote = require('Storage/Admin/Remote') Remote = require('Storage/Admin/Remote')
; ;
_.delay(function () {
var
f1 = Utils.settingsSaveHelperSimpleFunction(self.title.trigger, self),
f2 = Utils.settingsSaveHelperSimpleFunction(self.loadingDesc.trigger, self)
;
self.title.subscribe(function (sValue) {
Remote.saveAdminConfig(f1, {
'Title': Utils.trim(sValue)
});
});
self.loadingDesc.subscribe(function (sValue) {
Remote.saveAdminConfig(f2, {
'LoadingDescription': Utils.trim(sValue)
});
});
}, 50);
if (this.capa) if (this.capa)
{ {
_.delay(function () { _.delay(function () {
var var
f1 = Utils.settingsSaveHelperSimpleFunction(self.title.trigger, self),
f2 = Utils.settingsSaveHelperSimpleFunction(self.loadingDesc.trigger, self),
f3 = Utils.settingsSaveHelperSimpleFunction(self.loginLogo.trigger, self), f3 = Utils.settingsSaveHelperSimpleFunction(self.loginLogo.trigger, self),
f4 = Utils.settingsSaveHelperSimpleFunction(self.loginDescription.trigger, self), f4 = Utils.settingsSaveHelperSimpleFunction(self.loginDescription.trigger, self),
f5 = Utils.settingsSaveHelperSimpleFunction(self.loginCss.trigger, self) f5 = Utils.settingsSaveHelperSimpleFunction(self.loginCss.trigger, self)
; ;
self.title.subscribe(function (sValue) {
Remote.saveAdminConfig(f1, {
'Title': Utils.trim(sValue)
});
});
self.loadingDesc.subscribe(function (sValue) {
Remote.saveAdminConfig(f2, {
'LoadingDescription': Utils.trim(sValue)
});
});
self.loginLogo.subscribe(function (sValue) { self.loginLogo.subscribe(function (sValue) {
Remote.saveAdminConfig(f3, { Remote.saveAdminConfig(f3, {
'LoginLogo': Utils.trim(sValue) 'LoginLogo': Utils.trim(sValue)
@ -88,7 +96,13 @@
}); });
}); });
}, 50); self.loginPowered.subscribe(function (bValue) {
Remote.saveAdminConfig(null, {
'LoginPowered': bValue ? '1' : '0'
});
});
}, 100);
} }
}; };

View file

@ -1,7 +1,7 @@
.b-admin-branding { .b-admin-branding {
.disabled-form { .disabled-form {
opacity: 0.5; opacity: 0.4;
} }
} }

View file

@ -206,6 +206,14 @@ select {
margin-left: 0; margin-left: 0;
} }
.alert a {
color: #c09853;
}
.alert.alert-info a {
color: #3a87ad;
}
.alert.alert-error a { .alert.alert-error a {
color: #b94a48; color: #b94a48;
} }

View file

@ -28,7 +28,7 @@
this.adminManLoadingVisibility = Data.adminManLoadingVisibility; this.adminManLoadingVisibility = Data.adminManLoadingVisibility;
this.capa = !!Settings.settingsGet('PremType'); this.capa = !!Settings.settingsGet('PremType');
this.capa = false; this.capa = false; // TODO
kn.constructorEnd(this); kn.constructorEnd(this);
} }

View file

@ -42,6 +42,7 @@
this.logoImg = Utils.trim(Settings.settingsGet('LoginLogo')); this.logoImg = Utils.trim(Settings.settingsGet('LoginLogo'));
this.loginDescription = Utils.trim(Settings.settingsGet('LoginDescription')); this.loginDescription = Utils.trim(Settings.settingsGet('LoginDescription'));
this.logoCss = Utils.trim(Settings.settingsGet('LoginCss')); this.logoCss = Utils.trim(Settings.settingsGet('LoginCss'));
this.logoPowered = !!Settings.settingsGet('LoginPowered');
this.emailError = ko.observable(false); this.emailError = ko.observable(false);
this.passwordError = ko.observable(false); this.passwordError = ko.observable(false);

View file

@ -29,7 +29,6 @@ var
gulp = require('gulp'), gulp = require('gulp'),
concat = require('gulp-concat-util'), concat = require('gulp-concat-util'),
header = require('gulp-header'), header = require('gulp-header'),
footer = require('gulp-footer'),
eol = require('gulp-eol'), eol = require('gulp-eol'),
rename = require('gulp-rename'), rename = require('gulp-rename'),
replace = require('gulp-replace'), replace = require('gulp-replace'),
@ -225,8 +224,8 @@ gulp.task('js:boot', function() {
gulp.task('js:encrypt', function() { gulp.task('js:encrypt', function() {
return gulp.src(cfg.paths.js.encrypt.src) return gulp.src(cfg.paths.js.encrypt.src)
.pipe(concat(cfg.paths.js.encrypt.name)) .pipe(concat(cfg.paths.js.encrypt.name))
.pipe(header(cfg.paths.js.encrypt.header || '')) .pipe(concat.header(cfg.paths.js.encrypt.header || ''))
.pipe(footer(cfg.paths.js.encrypt.footer || '')) .pipe(concat.footer(cfg.paths.js.encrypt.footer || ''))
.pipe(uglify(cfg.uglify)) .pipe(uglify(cfg.uglify))
.pipe(eol('\n', true)) .pipe(eol('\n', true))
.pipe(gulp.dest(cfg.paths.js.encrypt.dest)) .pipe(gulp.dest(cfg.paths.js.encrypt.dest))

View file

@ -57,7 +57,6 @@
"gulp-rename": "*", "gulp-rename": "*",
"gulp-replace": "*", "gulp-replace": "*",
"gulp-header": "*", "gulp-header": "*",
"gulp-footer": "*",
"gulp-eol": "*", "gulp-eol": "*",
"gulp-minify-css": "*", "gulp-minify-css": "*",
"gulp-autoprefixer": "*", "gulp-autoprefixer": "*",

View file

@ -1,164 +1,164 @@
<?php <?php
/* /*
* This file is part of MailSo. * This file is part of MailSo.
* *
* (c) 2014 Usenko Timur * (c) 2014 Usenko Timur
* *
* For the full copyright and license information, please view the LICENSE * For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace MailSo\Cache; namespace MailSo\Cache;
/** /**
* @category MailSo * @category MailSo
* @package Cache * @package Cache
*/ */
class CacheClient class CacheClient
{ {
/** /**
* @var \MailSo\Cache\DriverInterface * @var \MailSo\Cache\DriverInterface
*/ */
private $oDriver; private $oDriver;
/** /**
* @var string * @var string
*/ */
private $sCacheIndex; private $sCacheIndex;
/** /**
* @access private * @access private
*/ */
private function __construct() private function __construct()
{ {
$this->oDriver = null; $this->oDriver = null;
$this->sCacheIndex = ''; $this->sCacheIndex = '';
} }
/** /**
* @return \MailSo\Cache\CacheClient * @return \MailSo\Cache\CacheClient
*/ */
public static function NewInstance() public static function NewInstance()
{ {
return new self(); return new self();
} }
/** /**
* @param string $sKey * @param string $sKey
* @param string $sValue * @param string $sValue
* *
* @return bool * @return bool
*/ */
public function Set($sKey, $sValue) public function Set($sKey, $sValue)
{ {
return $this->oDriver ? $this->oDriver->Set($sKey.$this->sCacheIndex, $sValue) : false; return $this->oDriver ? $this->oDriver->Set($sKey.$this->sCacheIndex, $sValue) : false;
} }
/** /**
* @param string $sKey * @param string $sKey
* *
* @return bool * @return bool
*/ */
public function SetTimer($sKey) public function SetTimer($sKey)
{ {
return $this->Set($sKey.'/TIMER', time()); return $this->Set($sKey.'/TIMER', time());
} }
/** /**
* @param string $sKey * @param string $sKey
* @param string $bClearAfterGet = false * @param string $bClearAfterGet = false
* *
* @return string * @return string
*/ */
public function Get($sKey, $bClearAfterGet = false) public function Get($sKey, $bClearAfterGet = false)
{ {
$sValue = ''; $sValue = '';
if ($this->oDriver) if ($this->oDriver)
{ {
$sValue = $this->oDriver->Get($sKey.$this->sCacheIndex); $sValue = $this->oDriver->Get($sKey.$this->sCacheIndex);
} }
if ($bClearAfterGet) if ($bClearAfterGet)
{ {
$this->Delete($sKey); $this->Delete($sKey);
} }
return $sValue; return $sValue;
} }
/** /**
* @param string $sKey * @param string $sKey
* *
* @return int * @return int
*/ */
public function GetTimer($sKey) public function GetTimer($sKey)
{ {
$iTimer = 0; $iTimer = 0;
$sValue = $this->Get($sKey.'/TIMER'); $sValue = $this->Get($sKey.'/TIMER');
if (0 < strlen($sValue) && is_numeric($sValue)) if (0 < strlen($sValue) && is_numeric($sValue))
{ {
$iTimer = (int) $sValue; $iTimer = (int) $sValue;
} }
return $iTimer; return $iTimer;
} }
/** /**
* @param string $sKey * @param string $sKey
* *
* @return \MailSo\Cache\CacheClient * @return \MailSo\Cache\CacheClient
*/ */
public function Delete($sKey) public function Delete($sKey)
{ {
if ($this->oDriver) if ($this->oDriver)
{ {
$this->oDriver->Delete($sKey.$this->sCacheIndex); $this->oDriver->Delete($sKey.$this->sCacheIndex);
} }
return $this; return $this;
} }
/** /**
* @param \MailSo\Cache\DriverInterface $oDriver * @param \MailSo\Cache\DriverInterface $oDriver
* *
* @return \MailSo\Cache\CacheClient * @return \MailSo\Cache\CacheClient
*/ */
public function SetDriver(\MailSo\Cache\DriverInterface $oDriver) public function SetDriver(\MailSo\Cache\DriverInterface $oDriver)
{ {
$this->oDriver = $oDriver; $this->oDriver = $oDriver;
return $this; return $this;
} }
/** /**
* @param int $iTimeToClearInHours = 24 * @param int $iTimeToClearInHours = 24
* *
* @return bool * @return bool
*/ */
public function GC($iTimeToClearInHours = 24) public function GC($iTimeToClearInHours = 24)
{ {
return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false; return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false;
} }
/** /**
* @return bool * @return bool
*/ */
public function IsInited() public function IsInited()
{ {
return $this->oDriver instanceof \MailSo\Cache\DriverInterface; return $this->oDriver instanceof \MailSo\Cache\DriverInterface;
} }
/** /**
* @param string $sCacheIndex * @param string $sCacheIndex
* *
* @return \MailSo\Cache\CacheClient * @return \MailSo\Cache\CacheClient
*/ */
public function SetCacheIndex($sCacheIndex) public function SetCacheIndex($sCacheIndex)
{ {
$this->sCacheIndex = 0 < \strlen($sCacheIndex) ? "\x0".$sCacheIndex : ''; $this->sCacheIndex = 0 < \strlen($sCacheIndex) ? "\x0".$sCacheIndex : '';
return $this; return $this;
} }
} }

View file

@ -330,7 +330,7 @@ class BodyStructure
{ {
$mResult = $this->SearchPlainParts(); $mResult = $this->SearchPlainParts();
} }
return $mResult; return $mResult;
} }
@ -465,7 +465,7 @@ class BodyStructure
* @param array $aParams * @param array $aParams
* @param string $sParamName * @param string $sParamName
* @param string $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8 * @param string $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8
* *
* @return string * @return string
*/ */
private static function decodeAttrParamenter($aParams, $sParamName, $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8) private static function decodeAttrParamenter($aParams, $sParamName, $sCharset = \MailSo\Base\Enumerations\Charset::UTF_8)
@ -477,7 +477,7 @@ class BodyStructure
} }
else if (isset($aParams[$sParamName.'*'])) else if (isset($aParams[$sParamName.'*']))
{ {
$aValueParts = \explode('\'\'', $aParams[$sParamName.'*'], 2); $aValueParts = \explode("''", $aParams[$sParamName.'*'], 2);
if (\is_array($aValueParts) && 2 === \count($aValueParts)) if (\is_array($aValueParts) && 2 === \count($aValueParts))
{ {
$sCharset = isset($aValueParts[0]) ? $aValueParts[0] : \MailSo\Base\Enumerations\Charset::UTF_8; $sCharset = isset($aValueParts[0]) ? $aValueParts[0] : \MailSo\Base\Enumerations\Charset::UTF_8;
@ -490,30 +490,30 @@ class BodyStructure
$sResult = \urldecode($aParams[$sParamName.'*']); $sResult = \urldecode($aParams[$sParamName.'*']);
} }
} }
else if (isset($aParams[$sParamName.'*0*'])) else
{ {
$sCharset = ''; $sCharset = '';
$sCharsetIndex = -1;
$aFileNames = array(); $aFileNames = array();
foreach ($aParams as $sName => $sValue) foreach ($aParams as $sName => $sValue)
{ {
$aMatches = array(); $aMatches = array();
if ($sParamName.'*0*' === $sName) if (\preg_match('/^'.\preg_quote($sParamName, '/').'\*([0-9]+)\*$/i', $sName, $aMatches))
{ {
if (0 === \strlen($sCharset)) $iIndex = (int) $aMatches[1];
if ($sCharsetIndex < $iIndex && false !== \strpos($sValue, "''"))
{ {
$aValueParts = \explode('\'\'', $sValue, 2); $aValueParts = \explode("''", $sValue, 2);
if (\is_array($aValueParts) && 2 === \count($aValueParts) && 0 < \strlen($aValueParts[0])) if (\is_array($aValueParts) && 2 === \count($aValueParts) && 0 < \strlen($aValueParts[0]))
{ {
$sCharsetIndex = $iIndex;
$sCharset = $aValueParts[0]; $sCharset = $aValueParts[0];
$sValue = $aValueParts[1]; $sValue = $aValueParts[1];
} }
} }
$aFileNames[0] = $sValue; $aFileNames[$iIndex] = $sValue;
}
else if ($sParamName.'*0*' !== $sName && \preg_match('/^'.\preg_quote($sParamName, '/').'\*([0-9]+)\*$/i', $sName, $aMatches) && 0 < \strlen($aMatches[1]))
{
$aFileNames[(int) $aMatches[1]] = $sValue;
} }
} }
@ -662,7 +662,7 @@ class BodyStructure
{ {
$sCharset = $aBodyParams['charset']; $sCharset = $aBodyParams['charset'];
} }
if (\is_array($aBodyParams)) if (\is_array($aBodyParams))
{ {
$sName = self::decodeAttrParamenter($aBodyParams, 'name', $sContentType); $sName = self::decodeAttrParamenter($aBodyParams, 'name', $sContentType);
@ -675,7 +675,7 @@ class BodyStructure
{ {
return null; return null;
} }
$sContentID = $aBodyStructure[3]; $sContentID = $aBodyStructure[3];
} }
@ -685,7 +685,7 @@ class BodyStructure
{ {
return null; return null;
} }
$sDescription = $aBodyStructure[4]; $sDescription = $aBodyStructure[4];
} }
@ -867,7 +867,7 @@ class BodyStructure
/** /**
* @param array $aList * @param array $aList
* @param string $sPartID * @param string $sPartID
* *
* @return array|null * @return array|null
*/ */
private static function findPartByIndexInArray(array $aList, $sPartID) private static function findPartByIndexInArray(array $aList, $sPartID)

View file

@ -26,7 +26,7 @@ class ParameterCollection extends \MailSo\Base\Collection
{ {
parent::__construct(); parent::__construct();
if (0 < strlen($sRawParams)) if (0 < \strlen($sRawParams))
{ {
$this->Parse($sRawParams); $this->Parse($sRawParams);
} }
@ -74,12 +74,12 @@ class ParameterCollection extends \MailSo\Base\Collection
public function ParameterValueByName($sName) public function ParameterValueByName($sName)
{ {
$sResult = ''; $sResult = '';
$sName = trim($sName); $sName = \trim($sName);
$aParams =& $this->GetAsArray(); $aParams =& $this->GetAsArray();
foreach ($aParams as /* @var $oParam \MailSo\Mime\ParameterCollection */ $oParam) foreach ($aParams as /* @var $oParam \MailSo\Mime\ParameterCollection */ $oParam)
{ {
if (strtolower($sName) === strtolower($oParam->Name())) if (\strtolower($sName) === \strtolower($oParam->Name()))
{ {
$sResult = $oParam->Value(); $sResult = $oParam->Value();
break; break;
@ -98,7 +98,7 @@ class ParameterCollection extends \MailSo\Base\Collection
{ {
$this->Clear(); $this->Clear();
$aDataToParse = explode(';', $sRawParams); $aDataToParse = \explode(';', $sRawParams);
foreach ($aDataToParse as $sParam) foreach ($aDataToParse as $sParam)
{ {
@ -122,13 +122,13 @@ class ParameterCollection extends \MailSo\Base\Collection
foreach ($aParams as /* @var $oParam \MailSo\Mime\Parameter */ $oParam) foreach ($aParams as /* @var $oParam \MailSo\Mime\Parameter */ $oParam)
{ {
$sLine = $oParam->ToString($bConvertSpecialsName); $sLine = $oParam->ToString($bConvertSpecialsName);
if (0 < strlen($sLine)) if (0 < \strlen($sLine))
{ {
$aResult[] = $sLine; $aResult[] = $sLine;
} }
} }
return 0 < count($aResult) ? implode('; ', $aResult) : ''; return 0 < \count($aResult) ? \implode('; ', $aResult) : '';
} }
/** /**
@ -147,8 +147,8 @@ class ParameterCollection extends \MailSo\Base\Collection
$aMatch = array(); $aMatch = array();
$sParamName = $oParam->Name(); $sParamName = $oParam->Name();
if (preg_match('/([^\*]+)\*([\d]{1,2})\*/', $sParamName, $aMatch) && isset($aMatch[1], $aMatch[2]) if (\preg_match('/([^\*]+)\*([\d]{1,2})\*/', $sParamName, $aMatch) && isset($aMatch[1], $aMatch[2])
&& 0 < strlen($aMatch[1]) && is_numeric($aMatch[2])) && 0 < \strlen($aMatch[1]) && \is_numeric($aMatch[2]))
{ {
if (!isset($aPreParams[$aMatch[1]])) if (!isset($aPreParams[$aMatch[1]]))
{ {
@ -156,16 +156,20 @@ class ParameterCollection extends \MailSo\Base\Collection
} }
$sValue = $oParam->Value(); $sValue = $oParam->Value();
$aValueParts = explode('\'\'', $sValue, 2);
if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[1])) if (false !== \strpos($sValue, "''"))
{ {
$sCharset = $aValueParts[0]; $aValueParts = \explode("''", $sValue, 2);
$sValue = $aValueParts[1]; if (\is_array($aValueParts) && 2 === \count($aValueParts) && 0 < \strlen($aValueParts[1]))
{
$sCharset = $aValueParts[0];
$sValue = $aValueParts[1];
}
} }
$aPreParams[$aMatch[1]][(int) $aMatch[2]] = $sValue; $aPreParams[$aMatch[1]][(int) $aMatch[2]] = $sValue;
} }
else if (preg_match('/([^\*]+)\*/', $sParamName, $aMatch) && isset($aMatch[1])) else if (\preg_match('/([^\*]+)\*/', $sParamName, $aMatch) && isset($aMatch[1]))
{ {
if (!isset($aPreParams[$aMatch[1]])) if (!isset($aPreParams[$aMatch[1]]))
{ {
@ -173,11 +177,14 @@ class ParameterCollection extends \MailSo\Base\Collection
} }
$sValue = $oParam->Value(); $sValue = $oParam->Value();
$aValueParts = explode('\'\'', $sValue, 2); if (false !== \strpos($sValue, "''"))
if (is_array($aValueParts) && 2 === count($aValueParts) && 0 < strlen($aValueParts[1]))
{ {
$sCharset = $aValueParts[0]; $aValueParts = \explode("''", $sValue, 2);
$sValue = $aValueParts[1]; if (\is_array($aValueParts) && 2 === \count($aValueParts) && 0 < \strlen($aValueParts[1]))
{
$sCharset = $aValueParts[0];
$sValue = $aValueParts[1];
}
} }
$aPreParams[$aMatch[1]][0] = $sValue; $aPreParams[$aMatch[1]][0] = $sValue;
@ -191,10 +198,10 @@ class ParameterCollection extends \MailSo\Base\Collection
foreach ($aPreParams as $sName => $aValues) foreach ($aPreParams as $sName => $aValues)
{ {
ksort($aValues); ksort($aValues);
$sResult = implode(array_values($aValues)); $sResult = \implode(\array_values($aValues));
$sResult = urldecode($sResult); $sResult = \urldecode($sResult);
if (0 < strlen($sCharset)) if (0 < \strlen($sCharset))
{ {
$sResult = \MailSo\Base\Utils::ConvertEncoding($sResult, $sResult = \MailSo\Base\Utils::ConvertEncoding($sResult,
$sCharset, \MailSo\Base\Enumerations\Charset::UTF_8); $sCharset, \MailSo\Base\Enumerations\Charset::UTF_8);

View file

@ -958,7 +958,14 @@ class Actions
*/ */
private function PremType() private function PremType()
{ {
return false; static $bResult = null;
if (null === $bResult)
{
// $bResult = $this->licenseParser($this->licenseHelper(false, true));
$bResult = true;
}
return $bResult;
} }
/** /**
@ -993,6 +1000,7 @@ class Actions
'LoginLogo' => '', 'LoginLogo' => '',
'LoginDescription' => '', 'LoginDescription' => '',
'LoginCss' => '', 'LoginCss' => '',
'LoginPowered' => true,
'Token' => $oConfig->Get('security', 'csrf_protection', false) ? \RainLoop\Utils::GetCsrfToken() : '', 'Token' => $oConfig->Get('security', 'csrf_protection', false) ? \RainLoop\Utils::GetCsrfToken() : '',
'InIframe' => (bool) $oConfig->Get('labs', 'in_iframe', false), 'InIframe' => (bool) $oConfig->Get('labs', 'in_iframe', false),
'AllowAdminPanel' => (bool) $oConfig->Get('security', 'allow_admin_panel', true), 'AllowAdminPanel' => (bool) $oConfig->Get('security', 'allow_admin_panel', true),
@ -1038,14 +1046,15 @@ class Actions
$aResult['AuthAccountHash'] = $sAuthAccountHash; $aResult['AuthAccountHash'] = $sAuthAccountHash;
} }
if ($this->PremType() || true) $aResult['Title'] = $oConfig->Get('webmail', 'title', '');
{ $aResult['LoadingDescription'] = $oConfig->Get('webmail', 'loading_description', '');
$aResult['Title'] = $oConfig->Get('webmail', 'title', '');
$aResult['LoadingDescription'] = $oConfig->Get('webmail', 'loading_description', '');
if ($this->PremType())
{
$aResult['LoginLogo'] = $oConfig->Get('branding', 'login_logo', ''); $aResult['LoginLogo'] = $oConfig->Get('branding', 'login_logo', '');
$aResult['LoginDescription'] = $oConfig->Get('branding', 'login_desc', ''); $aResult['LoginDescription'] = $oConfig->Get('branding', 'login_desc', '');
$aResult['LoginCss'] = $oConfig->Get('branding', 'login_css', ''); $aResult['LoginCss'] = $oConfig->Get('branding', 'login_css', '');
$aResult['LoginPowered'] = !!$oConfig->Get('branding', 'login_powered', true);
} }
$oSettings = null; $oSettings = null;
@ -2460,14 +2469,15 @@ class Actions
$this->setConfigFromParams($oConfig, 'DetermineUserLanguage', 'login', 'determine_user_language', 'bool'); $this->setConfigFromParams($oConfig, 'DetermineUserLanguage', 'login', 'determine_user_language', 'bool');
$this->setConfigFromParams($oConfig, 'DetermineUserDomain', 'login', 'determine_user_domain', 'bool'); $this->setConfigFromParams($oConfig, 'DetermineUserDomain', 'login', 'determine_user_domain', 'bool');
if ($this->PremType() || true) $this->setConfigFromParams($oConfig, 'Title', 'webmail', 'title', 'string');
{ $this->setConfigFromParams($oConfig, 'LoadingDescription', 'webmail', 'loading_description', 'string');
$this->setConfigFromParams($oConfig, 'Title', 'webmail', 'title', 'string');
$this->setConfigFromParams($oConfig, 'LoadingDescription', 'webmail', 'loading_description', 'string');
if ($this->HasOneOfActionParams(array('LoginLogo', 'LoginDescription', 'LoginCss', 'LoginPowered')) && $this->PremType())
{
$this->setConfigFromParams($oConfig, 'LoginLogo', 'branding', 'login_logo', 'string'); $this->setConfigFromParams($oConfig, 'LoginLogo', 'branding', 'login_logo', 'string');
$this->setConfigFromParams($oConfig, 'LoginDescription', 'branding', 'login_desc', 'string'); $this->setConfigFromParams($oConfig, 'LoginDescription', 'branding', 'login_desc', 'string');
$this->setConfigFromParams($oConfig, 'LoginCss', 'branding', 'login_css', 'string'); $this->setConfigFromParams($oConfig, 'LoginCss', 'branding', 'login_css', 'string');
$this->setConfigFromParams($oConfig, 'LoginPowered', 'branding', 'login_powered', 'bool');
} }
$this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool'); $this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool');
@ -2567,7 +2577,7 @@ class Actions
/** /**
* @return string * @return string
*/ */
public function licenseHelper($sForce = false, $iCacheTimeInMin = 5) public function licenseHelper($sForce = false, $bLongCache = false, $iFastCacheTimeInMin = 5, $iLongCacheTimeInDays = 2)
{ {
$sDomain = APP_SITE; $sDomain = APP_SITE;
@ -2582,15 +2592,31 @@ class Actions
$sValue = ''; $sValue = '';
if (!$sForce && $oCacher) if (!$sForce && $oCacher)
{ {
$iTime = $oCacher->GetTimer(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain)); if (!$bLongCache)
if ($iTime + 60 * $iCacheTimeInMin > \time())
{ {
$sValue = $oCacher->Get(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain)); $iTime = $oCacher->GetTimer(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain));
if ($iTime + 60 * $iFastCacheTimeInMin > \time())
{
$sValue = $oCacher->Get(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain));
}
}
else
{
$iTime = $oCacher->GetTimer(\RainLoop\KeyPathHelper::LicensingDomainKeyOtherValue($sDomain));
if ($iTime + (60 * 60 * 24) * $iLongCacheTimeInDays > \time())
{
$sValue = $oCacher->Get(\RainLoop\KeyPathHelper::LicensingDomainKeyOtherValue($sDomain));
}
} }
} }
if (0 === \strlen($sValue)) if (0 === \strlen($sValue))
{ {
if ($bLongCache && (!$oCacher || !$oCacher->SetTimer(\RainLoop\KeyPathHelper::LicensingDomainKeyOtherValue($sDomain))))
{
return 'NO';
}
$iCode = 0; $iCode = 0;
$sContentType = ''; $sContentType = '';
@ -2607,14 +2633,33 @@ class Actions
if ($oCacher) if ($oCacher)
{ {
$oCacher->Set(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain), $sValue);
$oCacher->SetTimer(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain)); $oCacher->SetTimer(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain));
$oCacher->Set(\RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain), $sValue);
$oCacher->Set(\RainLoop\KeyPathHelper::LicensingDomainKeyOtherValue($sDomain), $sValue);
} }
} }
return $sValue; return $sValue;
} }
/**
* @param string $sInput
*
* @return bool
*/
public function licenseParser($sInput)
{
$aMatch = array();
if (\preg_match('/^EXPIRED:([\d]+)$/', $sInput, $aMatch))
{
$iTime = (int) $aMatch[1];
return \time() < $iTime;
}
return false;
}
/** /**
* @return array * @return array
*/ */
@ -7183,6 +7228,24 @@ class Actions
return isset($this->aCurrentActionParams[$sKey]); return isset($this->aCurrentActionParams[$sKey]);
} }
/**
* @param array $aKeys
*
* @return bool
*/
public function HasOneOfActionParams($aKeys)
{
foreach ($aKeys as $sKey)
{
if ($this->HasActionParam($sKey))
{
return true;
}
}
return false;
}
/** /**
* @param string $sUrl * @param string $sUrl
*/ */

View file

@ -81,7 +81,8 @@ class Application extends \RainLoop\Config\AbstractConfig
'branding' => array( 'branding' => array(
'login_logo' => array(''), 'login_logo' => array(''),
'login_desc' => array(''), 'login_desc' => array(''),
'login_css' => array('') 'login_css' => array(''),
'login_powered' => array(true)
), ),
'contacts' => array( 'contacts' => array(

View file

@ -64,6 +64,16 @@ class KeyPathHelper
return '/Licensing/DomainKey/Value/'.$sDomain; return '/Licensing/DomainKey/Value/'.$sDomain;
} }
/**
* @param string $sDomain
*
* @return string
*/
static public function LicensingDomainKeyOtherValue($sDomain)
{
return '/Licensing/DomainKeyOther/Value/'.$sDomain;
}
/** /**
* @param string $sRepo * @param string $sRepo
* @param string $sRepoFile * @param string $sRepoFile

View file

@ -1,66 +1,77 @@
<div class="b-admin-branding"> <div class="b-admin-branding">
<div class="row" data-bind="visible: !capa"> <div class="row" data-bind="visible: !capa">
<div class="alert alert-error span8" style="margin-top: 10px;"> <div class="alert span8" style="margin-top: 10px;">
<h4>Premium version only</h4> Full functionality available in <strong><a href="#/licensing">Premium version</a></strong> only.
<br />
<strong><a href="#/licensing">Licensing</a></strong>
</div> </div>
</div> </div>
<div class="form-horizontal" data-bind="css: {'disabled-form': !capa}"> <div class="form-horizontal">
<div class="legend"> <div>
Branding <div class="legend">
</div> Branding
<div class="control-group">
<label class="control-label">
Page Title
</label>
<div class="controls">
<input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: title, saveTrigger: title.trigger, enable: capa" />
<div data-bind="saveTrigger: title.trigger"></div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label">
<label class="control-label"> Page Title
Loading Description </label>
</label> <div class="controls">
<div class="controls"> <input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
<input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" data-bind="value: title, saveTrigger: title.trigger" />
data-bind="value: loadingDesc, saveTrigger: loadingDesc.trigger, enable: capa" /> <div data-bind="saveTrigger: title.trigger"></div>
<div data-bind="saveTrigger: loadingDesc.trigger"></div> </div>
</div>
<div class="control-group">
<label class="control-label">
Loading Description
</label>
<div class="controls">
<input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
data-bind="value: loadingDesc, saveTrigger: loadingDesc.trigger" />
<div data-bind="saveTrigger: loadingDesc.trigger"></div>
</div>
</div> </div>
</div> </div>
<br /> <br />
<div class="legend"> <div data-bind="css: {'disabled-form': !capa}">
Login Screen <div class="legend">
</div> Login Screen
<div class="control-group">
<label class="control-label">
Logo
</label>
<div class="controls">
<input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
placeholder="https://" data-bind="value: loginLogo, saveTrigger: loginLogo.trigger, enable: capa" />
<div data-bind="saveTrigger: loginLogo.trigger"></div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label">
<label class="control-label"> Logo
Description </label>
</label> <div class="controls">
<div class="controls"> <input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
<input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="https://" data-bind="value: loginLogo, saveTrigger: loginLogo.trigger, enable: capa" />
data-bind="value: loginDescription, saveTrigger: loginDescription.trigger, enable: capa" /> <div data-bind="saveTrigger: loginLogo.trigger"></div>
<div data-bind="saveTrigger: loginDescription.trigger"></div> </div>
</div> </div>
</div> <div class="control-group">
<div class="control-group"> <label class="control-label">
<label class="control-label"> Description
Custom CSS </label>
</label> <div class="controls">
<div class="controls"> <input type="text" class="span5" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
<textarea class="input-xxlarge" data-bind="value: loginCss, saveTrigger: loginCss.trigger, enable: capa" rows="7" spellcheck="true"></textarea> data-bind="value: loginDescription, saveTrigger: loginDescription.trigger, enable: capa" />
<div style="vertical-align: top;" data-bind="saveTrigger: loginCss.trigger"></div> <div data-bind="saveTrigger: loginDescription.trigger"></div>
</div>
</div>
<!-- <div class="control-group">
<label class="control-label"></label>
<div class="controls">
<label data-bind="click: function () { if (capa) { loginPowered(!loginPowered()); }}">
<i data-bind="css: loginPowered() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
Show "Powered by RainLoop" link
</label>
</div>
</div>-->
<div class="control-group">
<label class="control-label">
Custom CSS
</label>
<div class="controls">
<textarea class="input-xxlarge" data-bind="value: loginCss, saveTrigger: loginCss.trigger, enable: capa" rows="7" spellcheck="true"></textarea>
<div style="vertical-align: top;" data-bind="saveTrigger: loginCss.trigger"></div>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -113,7 +113,7 @@
</div> </div>
</div> </div>
</form> </form>
<div class="e-powered thm-powered"> <div class="e-powered thm-powered" data-bind="visible: logoPowered">
Powered by <a href="http://rainloop.net" target="_blank">RainLoop</a> Powered by <a href="http://rainloop.net" target="_blank">RainLoop</a>
</div> </div>
</div> </div>