mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-29 20:19:22 +03:00
Added "Custom Theme Configuration" (background)
This commit is contained in:
parent
0587d66d45
commit
ef81865ef2
45 changed files with 1151 additions and 73654 deletions
|
|
@ -68,5 +68,3 @@ else if (\function_exists('RainLoopSplAutoloadRegisterFunction'))
|
|||
{
|
||||
\spl_autoload_unregister('RainLoopSplAutoloadRegisterFunction');
|
||||
}
|
||||
|
||||
return '';
|
||||
|
|
@ -1051,8 +1051,6 @@ class Actions
|
|||
'Plugins' => array()
|
||||
);
|
||||
|
||||
// $aResult['MaterialDesign'] = false;
|
||||
|
||||
if ($aResult['UseRsaEncryption'] &&
|
||||
\file_exists(APP_PRIVATE_DATA.'rsa/public') && \file_exists(APP_PRIVATE_DATA.'rsa/private'))
|
||||
{
|
||||
|
|
@ -1075,7 +1073,6 @@ class Actions
|
|||
$aResult['AuthAccountHash'] = $sAuthAccountHash;
|
||||
}
|
||||
|
||||
|
||||
if ($this->PremType())
|
||||
{
|
||||
$aResult['Title'] = $oConfig->Get('webmail', 'title', '');
|
||||
|
|
@ -1304,6 +1301,8 @@ class Actions
|
|||
$aResult['EnableTwoFactor'] = false;
|
||||
$aResult['ParentEmail'] = '';
|
||||
$aResult['InterfaceAnimation'] = \RainLoop\Enumerations\InterfaceAnimation::NORMAL;
|
||||
$aResult['UserBackgroundName'] = '';
|
||||
$aResult['UserBackgroundHash'] = '';
|
||||
|
||||
if (!$bAdmin && $oSettings instanceof \RainLoop\Settings)
|
||||
{
|
||||
|
|
@ -1334,6 +1333,12 @@ class Actions
|
|||
$aResult['UseCheckboxesInList'] = (bool) $oSettings->GetConf('UseCheckboxesInList', $aResult['UseCheckboxesInList']);
|
||||
$aResult['InterfaceAnimation'] = (string) $oSettings->GetConf('InterfaceAnimation', $aResult['InterfaceAnimation']);
|
||||
|
||||
if ($oConfig->Get('webmail', 'allow_user_background', false))
|
||||
{
|
||||
$aResult['UserBackgroundName'] = (string) $oSettings->GetConf('UserBackgroundName', $aResult['UserBackgroundName']);
|
||||
$aResult['UserBackgroundHash'] = (string) $oSettings->GetConf('UserBackgroundHash', $aResult['UserBackgroundHash']);
|
||||
}
|
||||
|
||||
$aResult['DefaultIdentityID'] = $oSettings->GetConf('DefaultIdentityID', $oAccount ? $oAccount->Email() : $aResult['DefaultIdentityID']);
|
||||
$aResult['DisplayName'] = $oSettings->GetConf('DisplayName', $aResult['DisplayName']);
|
||||
$aResult['ReplyTo'] = $oSettings->GetConf('ReplyTo', $aResult['ReplyTo']);
|
||||
|
|
@ -1356,10 +1361,11 @@ class Actions
|
|||
$aResult['AllowTwitterSocial'] = false;
|
||||
}
|
||||
|
||||
$sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash());
|
||||
$sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash().$aResult['UserBackgroundHash']);
|
||||
|
||||
$sTheme = $this->ValidateTheme($sTheme);
|
||||
$sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$sStaticCache.'/';
|
||||
$sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$sStaticCache.'/Hash/'.
|
||||
(empty($aResult['UserBackgroundHash']) ? '-' : $aResult['UserBackgroundHash']).'/';
|
||||
|
||||
$bUserLanguage = false;
|
||||
if (!$bAdmin && !$aResult['Auth'] && !empty($_COOKIE['rllang']) &&
|
||||
|
|
@ -4507,7 +4513,7 @@ class Actions
|
|||
*/
|
||||
public function DoMessageList()
|
||||
{
|
||||
// sleep(5);
|
||||
// sleep(2);
|
||||
// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList);
|
||||
|
||||
$sFolder = '';
|
||||
|
|
@ -6300,6 +6306,32 @@ class Actions
|
|||
return $this->DefaultResponse(__FUNCTION__, $aResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function DoClearUserBackground()
|
||||
{
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
||||
if ($oAccount && $oSettings)
|
||||
{
|
||||
$sHash = $oSettings->GetConf('UserBackgroundHash', '');
|
||||
if (!empty($sHash))
|
||||
{
|
||||
$this->StorageProvider()->Clear(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
\RainLoop\KeyPathHelper::PublicFile($sHash)
|
||||
);
|
||||
}
|
||||
|
||||
$oSettings->SetConf('UserBackgroundName', '');
|
||||
$oSettings->SetConf('UserBackgroundHash', '');
|
||||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, $oAccount && $oSettings ? $this->SettingsProvider()->Save($oAccount, $oSettings) : false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
|
@ -6307,45 +6339,88 @@ class Actions
|
|||
{
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
$bResponse = false;
|
||||
$sName = '';
|
||||
$sHash = '';
|
||||
|
||||
$aFile = $this->GetActionParam('File', null);
|
||||
$iError = $this->GetActionParam('Error', \RainLoop\Enumerations\UploadError::UNKNOWN);
|
||||
|
||||
if ($oAccount && UPLOAD_ERR_OK === $iError && \is_array($aFile))
|
||||
{
|
||||
$sSavedName = 'upload-post-'.\md5($aFile['name'].$aFile['tmp_name']);
|
||||
if (!$this->FilesProvider()->MoveUploadedFile($oAccount, $sSavedName, $aFile['tmp_name']))
|
||||
$sMimeType = \strtolower(\MailSo\Base\Utils::MimeContentType($aFile['name']));
|
||||
if (\in_array($sMimeType, array('image/png', 'image/jpg', 'image/jpeg')))
|
||||
{
|
||||
$iError = \RainLoop\Enumerations\UploadError::ON_SAVING;
|
||||
$sSavedName = 'upload-post-'.\md5($aFile['name'].$aFile['tmp_name']);
|
||||
if (!$this->FilesProvider()->MoveUploadedFile($oAccount, $sSavedName, $aFile['tmp_name']))
|
||||
{
|
||||
$iError = \RainLoop\Enumerations\UploadError::ON_SAVING;
|
||||
}
|
||||
else
|
||||
{
|
||||
$rData = $this->FilesProvider()->GetFile($oAccount, $sSavedName);
|
||||
if (@\is_resource($rData))
|
||||
{
|
||||
$sData = @\stream_get_contents($rData);
|
||||
if (!empty($sData) && 0 < \strlen($sData))
|
||||
{
|
||||
$iLimit = 3;
|
||||
while (true)
|
||||
{
|
||||
$iLimit--;
|
||||
if (0 > $iLimit)
|
||||
{
|
||||
$sHash = '';
|
||||
break;
|
||||
}
|
||||
|
||||
$sHash = \sha1($sSavedName.\microtime(true).\rand(10000, 99999));
|
||||
if (!$this->StorageProvider()->Get(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
\RainLoop\KeyPathHelper::PublicFile($sHash), null))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($sHash))
|
||||
{
|
||||
if ($this->StorageProvider()->Put(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
\RainLoop\KeyPathHelper::PublicFile($sHash),
|
||||
'data:'.$sMimeType.':'.$sData
|
||||
))
|
||||
{
|
||||
$sName = $aFile['name'];
|
||||
|
||||
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
||||
if ($oSettings)
|
||||
{
|
||||
$oSettings->SetConf('UserBackgroundName', $sName);
|
||||
$oSettings->SetConf('UserBackgroundHash', $sHash);
|
||||
|
||||
$this->SettingsProvider()->Save($oAccount, $oSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($sData);
|
||||
}
|
||||
|
||||
if (@\is_resource($rData))
|
||||
{
|
||||
@\fclose($rData);
|
||||
}
|
||||
|
||||
unset($rData);
|
||||
}
|
||||
|
||||
$this->FilesProvider()->Clear($oAccount, $sSavedName);
|
||||
}
|
||||
else
|
||||
{
|
||||
$rData = $this->FilesProvider()->GetFile($oAccount, $sSavedName);
|
||||
if (@\is_resource($rData))
|
||||
{
|
||||
$sData = @\stream_get_contents($rData);
|
||||
if (!empty($sData) && 0 < \strlen($sData))
|
||||
{
|
||||
$bResponse = $this->StorageProvider()->Put($oAccount,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::USER,
|
||||
\RainLoop\KeyPathHelper::UserBackground($oAccount->Email()),
|
||||
\base64_encode($sData)
|
||||
);
|
||||
}
|
||||
|
||||
unset($sData);
|
||||
}
|
||||
|
||||
if (@\is_resource($rData))
|
||||
{
|
||||
@\fclose($rData);
|
||||
}
|
||||
|
||||
unset($rData);
|
||||
$iError = \RainLoop\Enumerations\UploadError::FILE_TYPE;
|
||||
}
|
||||
|
||||
$this->FilesProvider()->Clear($oAccount, $sSavedName);
|
||||
}
|
||||
|
||||
if (UPLOAD_ERR_OK !== $iError)
|
||||
|
|
@ -6359,7 +6434,10 @@ class Actions
|
|||
}
|
||||
}
|
||||
|
||||
return $this->DefaultResponse(__FUNCTION__, $bResponse);
|
||||
return $this->DefaultResponse(__FUNCTION__, !empty($sName) && !empty($sHash) ? array(
|
||||
'Name' => $sName,
|
||||
'Hash' => $sHash
|
||||
) : false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6819,6 +6897,44 @@ class Actions
|
|||
return $this->rawSmart(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function RawPublic()
|
||||
{
|
||||
$sRawKey = (string) $this->GetActionParam('RawKey', '');
|
||||
$this->verifyCacheByKey($sRawKey);
|
||||
|
||||
$sHash = $sRawKey;
|
||||
$sData = '';
|
||||
|
||||
if (!empty($sHash))
|
||||
{
|
||||
$sData = $this->StorageProvider()->Get(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
\RainLoop\KeyPathHelper::PublicFile($sHash)
|
||||
);
|
||||
}
|
||||
|
||||
$aMatch = array();
|
||||
if (!empty($sData) && 0 === \strpos($sData, 'data:') &&
|
||||
\preg_match('/^data:([^:]+):/', $sData, $aMatch) && !empty($aMatch[1]))
|
||||
{
|
||||
$sContentType = \trim($aMatch[1]);
|
||||
if (\in_array($sContentType, array('image/png', 'image/jpg', 'image/jpeg')))
|
||||
{
|
||||
$this->cacheByKey($sRawKey);
|
||||
|
||||
@\header('Content-Type: '.$sContentType);
|
||||
echo \preg_replace('/^data:[^:]+:/', '', $sData);
|
||||
unset($sData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFileName
|
||||
*
|
||||
|
|
|
|||
|
|
@ -25,13 +25,13 @@ class KeyPathHelper
|
|||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function UserBackground($sEmail)
|
||||
static public function PublicFile($sHash)
|
||||
{
|
||||
return '/UserBackground/Base64/'.$sEmail.'/Data/';
|
||||
return '/Public/Files/'.sha1($sHash).'/Data/';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -264,10 +264,11 @@ class ServiceActions
|
|||
|
||||
/**
|
||||
* @param string $sAction
|
||||
* @param int $iSizeLimit = 0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function privateUpload($sAction)
|
||||
private function privateUpload($sAction, $iSizeLimit = 0)
|
||||
{
|
||||
$oConfig = $this->Config();
|
||||
|
||||
|
|
@ -278,7 +279,7 @@ class ServiceActions
|
|||
$aFile = null;
|
||||
$sInputName = 'uploader';
|
||||
$iError = \RainLoop\Enumerations\UploadError::UNKNOWN;
|
||||
$iSizeLimit = ((int) $oConfig->Get('webmail', 'attachment_size_limit', 0)) * 1024 * 1024;
|
||||
$iSizeLimit = (0 < $iSizeLimit ? $iSizeLimit : ((int) $oConfig->Get('webmail', 'attachment_size_limit', 0))) * 1024 * 1024;
|
||||
|
||||
$iError = UPLOAD_ERR_OK;
|
||||
$_FILES = isset($_FILES) ? $_FILES : null;
|
||||
|
|
@ -364,7 +365,7 @@ class ServiceActions
|
|||
*/
|
||||
public function ServiceUploadContacts()
|
||||
{
|
||||
return $this->privateUpload('UploadContacts');
|
||||
return $this->privateUpload('UploadContacts', 5);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -372,7 +373,7 @@ class ServiceActions
|
|||
*/
|
||||
public function ServiceUploadBackground()
|
||||
{
|
||||
return $this->privateUpload('UploadBackground');
|
||||
return $this->privateUpload('UploadBackground', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -410,6 +411,8 @@ class ServiceActions
|
|||
{
|
||||
$this->oHttp->StatusHeader(404);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -616,7 +619,8 @@ class ServiceActions
|
|||
$sResult = '';
|
||||
|
||||
$bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2];
|
||||
$bJson = !empty($this->aPaths[7]) && 'Json' === $this->aPaths[7];
|
||||
$bJson = !empty($this->aPaths[9]) && 'Json' === $this->aPaths[9];
|
||||
$sHash = !empty($this->aPaths[8]) && 5 < \strlen($this->aPaths[8]) ? $this->aPaths[8] : '';
|
||||
|
||||
if ($bJson)
|
||||
{
|
||||
|
|
@ -648,7 +652,7 @@ class ServiceActions
|
|||
$sCacheFileName = '';
|
||||
if ($bCacheEnabled)
|
||||
{
|
||||
$sCacheFileName = \RainLoop\KeyPathHelper::CssCache($sTheme, $this->oActions->Plugins()->Hash());
|
||||
$sCacheFileName = \RainLoop\KeyPathHelper::CssCache($sTheme, $this->oActions->Plugins()->Hash(), $sHash);
|
||||
$sResult = $this->Cacher()->Get($sCacheFileName);
|
||||
}
|
||||
|
||||
|
|
@ -687,6 +691,15 @@ class ServiceActions
|
|||
|
||||
$sResult = $oLess->compile(\implode("\n", $aResult));
|
||||
|
||||
if (!empty($sHash))
|
||||
{
|
||||
$sResult .= "\n".'.thm-body {'.
|
||||
'background-image:none;'.
|
||||
'background-image: url("./?/Raw/0/Public/'.$sHash.'/") !important;'.
|
||||
'-moz-background-size:cover;-webkit-background-size:cover;background-size:cover;'.
|
||||
'}';
|
||||
}
|
||||
|
||||
if ($bCacheEnabled)
|
||||
{
|
||||
if (0 < \strlen($sCacheFileName))
|
||||
|
|
|
|||
|
|
@ -65,13 +65,13 @@
|
|||
value: capaThemes
|
||||
}
|
||||
}"></div>
|
||||
<!-- <div data-bind="component: {
|
||||
<div data-bind="component: {
|
||||
name: 'Checkbox',
|
||||
params: {
|
||||
label: 'Allow background selection on settings screen',
|
||||
value: capaUserBackground
|
||||
}
|
||||
}"></div>-->
|
||||
}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
<span class="i18n" data-i18n-text="SETTINGS_IDENTITY/LEGEND_IDENTITY"></span>
|
||||
</div>
|
||||
<div class="control-group g-ui-user-select-none">
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n-text="SETTINGS_IDENTITY/LABEL_DISPLAY_NAME"></span>
|
||||
</label>
|
||||
<label class="control-label">
|
||||
<span class="i18n" data-i18n-text="SETTINGS_IDENTITY/LABEL_DISPLAY_NAME"></span>
|
||||
</label>
|
||||
<div class="controls">
|
||||
<div data-bind="component: {
|
||||
name: 'Input',
|
||||
|
|
|
|||
|
|
@ -15,4 +15,30 @@
|
|||
<img class="e-image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-bind="attr: { 'src': themePreviewSrc }" />
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<div class="form-horizontal" data-bind="visible: capaUserBackground">
|
||||
<div class="legend">
|
||||
<span class="i18n" data-i18n-text="SETTINGS_THEMES/LEGEND_THEMES_CUSTOM"></span>
|
||||
</div>
|
||||
<div class="control-group g-ui-user-select-none">
|
||||
<div class="row" data-bind="visible: '' !== background.error()" style="margin-left: 0; margin-bottom: 10px;">
|
||||
<div class="alert alert-error span6" data-bind="text: background.error" style="margin-left: 0"></div>
|
||||
</div>
|
||||
<div class="row" data-bind="visible: '' !== background.name()" style="margin-left: 0">
|
||||
<a class="btn" data-bind="visible: '' !== background.name(), click: clearBackground">
|
||||
<i class="icon-remove"></i>
|
||||
</a>
|
||||
|
||||
<b data-bind="text: background.name"></b>
|
||||
</div>
|
||||
<div class="row" data-bind="visible: '' === background.name()" style="margin-left: 0">
|
||||
<a class="btn" data-bind="initDom: background.uploaderButton">
|
||||
<i data-bind="css: {'icon-image': !background.loading(), 'icon-spinner animated': background.loading()}"></i>
|
||||
|
||||
<span class="i18n" data-i18n-text="SETTINGS_THEMES/BUTTON_UPLOAD_BACKGROUND_IMAGE"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -2,28 +2,20 @@
|
|||
|
||||
if (defined('APP_VERSION'))
|
||||
{
|
||||
@ini_set('register_globals', 0);
|
||||
@ini_set('zend.ze1_compatibility_mode', 0);
|
||||
@ini_set('magic_quotes_gpc', 0);
|
||||
@ini_set('magic_quotes_runtime', 0);
|
||||
if (!defined('APP_START'))
|
||||
{
|
||||
define('APP_START', microtime(true));
|
||||
|
||||
@ini_set('suhosin.session.encrypt', 0);
|
||||
@ini_set('suhosin.get.max_name_length', 2014);
|
||||
@ini_set('suhosin.get.max_value_length', 2014);
|
||||
@ini_set('register_globals', 0);
|
||||
@ini_set('zend.ze1_compatibility_mode', 0);
|
||||
@ini_set('magic_quotes_gpc', 0);
|
||||
@ini_set('magic_quotes_runtime', 0);
|
||||
|
||||
define('APP_DEFAULT_DENY_ALL_HTACCESS', 'Deny from all
|
||||
define('APP_DEFAULT_DENY_ALL_HTACCESS', 'Deny from all
|
||||
<IfModule mod_autoindex.c>
|
||||
Options -Indexes
|
||||
</ifModule>');
|
||||
|
||||
if (isset($_ENV['RAINLOOP_INCLUDE_AS_VERSION']) && $_ENV['RAINLOOP_INCLUDE_AS_VERSION'])
|
||||
{
|
||||
$_ENV['RAINLOOP_INCLUDE_AS_VERSION'] = false;
|
||||
return APP_VERSION;
|
||||
}
|
||||
else if (!defined('APP_START'))
|
||||
{
|
||||
define('APP_START', microtime(true));
|
||||
define('APP_START_TIME', time());
|
||||
define('APP_REQUEST_RND', md5(APP_START.rand(10000, 99999).APP_START));
|
||||
define('APP_VERSION_ROOT_PATH', APP_INDEX_ROOT_PATH.'rainloop/v/'.APP_VERSION.'/');
|
||||
|
|
@ -196,7 +188,5 @@ Options -Indexes
|
|||
unset($sSite, $sSalt, $sData, $sInstalled, $sPrivateDataFolderInternalName);
|
||||
}
|
||||
|
||||
return include APP_VERSION_ROOT_PATH.'app/handle.php';
|
||||
include APP_VERSION_ROOT_PATH.'app/handle.php';
|
||||
}
|
||||
|
||||
return '';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue