From 51666d7c7ec1ef75ba1a5152df9e6ec876a1247a Mon Sep 17 00:00:00 2001 From: RainLoop Team Date: Thu, 5 Feb 2015 03:54:26 +0400 Subject: [PATCH] New logic for storage provider (breaking changes) --- README.md | 4 - dev/Common/Enums.js | 3 +- dev/Stores/Admin/Capa.js | 2 + dev/View/Popup/Domain.js | 6 +- .../0.0.0/app/libraries/RainLoop/Actions.php | 460 +++++++++++------- .../v/0.0.0/app/libraries/RainLoop/Api.php | 20 +- .../libraries/RainLoop/Enumerations/Capa.php | 1 + .../app/libraries/RainLoop/KeyPathHelper.php | 36 +- .../app/libraries/RainLoop/Model/Account.php | 8 + .../Providers/Files/DefaultStorage.php | 27 +- .../libraries/RainLoop/Providers/Settings.php | 10 - .../Providers/Settings/DefaultSettings.php | 20 +- .../Providers/Settings/SettingsInterface.php | 4 +- .../libraries/RainLoop/Providers/Storage.php | 27 +- .../Providers/Storage/DefaultStorage.php | 73 ++- .../Providers/Storage/StorageInterface.php | 5 + .../app/libraries/RainLoop/ServiceActions.php | 26 +- .../0.0.0/app/libraries/RainLoop/Settings.php | 16 +- .../v/0.0.0/app/libraries/RainLoop/Social.php | 2 + 19 files changed, 453 insertions(+), 297 deletions(-) diff --git a/README.md b/README.md index 088026b81..d5e5b2dcb 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ RainLoop Webmail ================== -[![Flattr donate button](http://api.flattr.com/button/button-static-50x60.png "Flattr This!")](https://flattr.com/thing/2999968 "RainLoop Webmail") - -## About - Simple, modern & fast web-based email client. Modest system requirements, decent performance, simple installation and upgrade, no database required - all these make RainLoop Webmail a perfect choice for your email solution. diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index 61bd73765..669042fa6 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -43,6 +43,7 @@ 'Themes': 'THEMES', 'UserBackground': 'USER_BACKGROUND', 'Sieve': 'SIEVE', + 'Filters': 'FILTERS', 'AttachmentThumbnails': 'ATTACHMENT_THUMBNAILS', 'AdditionalAccounts': 'ADDITIONAL_ACCOUNTS', 'AdditionalIdentities': 'ADDITIONAL_IDENTITIES' @@ -224,7 +225,7 @@ 'HtmlForced': 'HtmlForced', 'PlainForced': 'PlainForced' }; - + /** * @enum {number} */ diff --git a/dev/Stores/Admin/Capa.js b/dev/Stores/Admin/Capa.js index 65f6f9aeb..46c97974f 100644 --- a/dev/Stores/Admin/Capa.js +++ b/dev/Stores/Admin/Capa.js @@ -21,6 +21,7 @@ this.gravatar = ko.observable(false); this.attachmentThumbnails = ko.observable(false); this.sieve = ko.observable(false); + this.filters = ko.observable(false); this.themes = ko.observable(true); this.userBackground = ko.observable(false); this.openPGP = ko.observable(false); @@ -34,6 +35,7 @@ this.gravatar(Settings.capa(Enums.Capa.Gravatar)); this.attachmentThumbnails(Settings.capa(Enums.Capa.AttachmentThumbnails)); this.sieve(Settings.capa(Enums.Capa.Sieve)); + this.filters(Settings.capa(Enums.Capa.Filters)); this.themes(Settings.capa(Enums.Capa.Themes)); this.userBackground(Settings.capa(Enums.Capa.UserBackground)); this.openPGP(Settings.capa(Enums.Capa.OpenPGP)); diff --git a/dev/View/Popup/Domain.js b/dev/View/Popup/Domain.js index 35e7efaea..c6f1b809a 100644 --- a/dev/View/Popup/Domain.js +++ b/dev/View/Popup/Domain.js @@ -70,8 +70,6 @@ this.name = ko.observable(''); this.name.focused = ko.observable(false); - this.allowSieve = CapaAdminStore.sieve; - this.imapServer = ko.observable(''); this.imapPort = ko.observable('' + Consts.Values.ImapDefaulPort); this.imapSecure = ko.observable(Enums.ServerSecure.None); @@ -91,6 +89,10 @@ this.enableSmartPorts = ko.observable(false); + this.allowSieve = ko.computed(function () { + return CapaAdminStore.filters() && CapaAdminStore.sieve(); + }, this); + this.headerText = ko.computed(function () { var sName = this.name(); return this.edit() ? 'Edit Domain "' + sName + '"' : diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index e81914baa..3b12780a5 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -60,6 +60,11 @@ class Actions */ private $oStorageProvider; + /** + * @var \RainLoop\Providers\Storage + */ + private $oLocalStorageProvider; + /** * @var \RainLoop\Providers\Files */ @@ -75,6 +80,11 @@ class Actions */ private $oSettingsProvider; + /** + * @var \RainLoop\Providers\Settings + */ + private $oLocalSettingsProvider; + /** * @var \RainLoop\Providers\Filters */ @@ -126,8 +136,10 @@ class Actions $this->oCacher = null; $this->oStorageProvider = null; - $this->oFilesProvider = null; + $this->oLocalStorageProvider = null; $this->oSettingsProvider = null; + $this->oLocalSettingsProvider = null; + $this->oFilesProvider = null; $this->oFiltersProvider = null; $this->oDomainProvider = null; $this->oAddressBookProvider = null; @@ -241,10 +253,18 @@ class Actions // RainLoop\Providers\Storage\StorageInterface $oResult = new \RainLoop\Providers\Storage\DefaultStorage(APP_PRIVATE_DATA.'storage'); break; + case 'storage-local': + // RainLoop\Providers\Storage\StorageInterface + $oResult = new \RainLoop\Providers\Storage\DefaultStorage(APP_PRIVATE_DATA.'storage', true); + break; case 'settings': // RainLoop\Providers\Settings\SettingsInterface $oResult = new \RainLoop\Providers\Settings\DefaultSettings($this->StorageProvider()); break; + case 'settings-local': + // RainLoop\Providers\Settings\SettingsInterface + $oResult = new \RainLoop\Providers\Settings\DefaultSettings($this->StorageProvider(true)); + break; case 'login': // \RainLoop\Providers\Login\LoginInterface $oResult = new \RainLoop\Providers\Login\DefaultLogin(); @@ -635,20 +655,6 @@ class Actions return $this->oMailClient; } - /** - * @return \RainLoop\Providers\Settings - */ - public function SettingsProvider() - { - if (null === $this->oSettingsProvider) - { - $this->oSettingsProvider = new \RainLoop\Providers\Settings( - $this->fabrica('settings')); - } - - return $this->oSettingsProvider; - } - /** * @return \RainLoop\Providers\Filters */ @@ -694,17 +700,63 @@ class Actions } /** + * @param bool $bLocal = false + * * @return \RainLoop\Providers\Storage */ - public function StorageProvider() + public function StorageProvider($bLocal = false) { - if (null === $this->oStorageProvider) + if ($bLocal) { - $this->oStorageProvider = new \RainLoop\Providers\Storage( - $this->fabrica('storage')); + if (null === $this->oLocalStorageProvider) + { + $this->oLocalStorageProvider = new \RainLoop\Providers\Storage( + $this->fabrica('storage-local')); + } + + return $this->oLocalStorageProvider; + } + else + { + if (null === $this->oStorageProvider) + { + $this->oStorageProvider = new \RainLoop\Providers\Storage( + $this->fabrica('storage')); + } + + return $this->oStorageProvider; } - return $this->oStorageProvider; + return null; + } + + /** + * @return \RainLoop\Providers\Settings + */ + public function SettingsProvider($bLocal = false) + { + if ($bLocal) + { + if (null === $this->oLocalSettingsProvider) + { + $this->oLocalSettingsProvider = new \RainLoop\Providers\Settings( + $this->fabrica('settings-local')); + } + + return $this->oLocalSettingsProvider; + } + else + { + if (null === $this->oSettingsProvider) + { + $this->oSettingsProvider = new \RainLoop\Providers\Settings( + $this->fabrica('settings')); + } + + return $this->oSettingsProvider; + } + + return null; } /** @@ -1118,14 +1170,6 @@ class Actions return $bResult; } - /** - * @return bool - */ - private function UseSieve() - { - return $this->Config()->Get('capa', 'filters', false); - } - /** * @param bool $bAdmin * @param string $sAuthAccountHash = '' @@ -1184,7 +1228,6 @@ class Actions 'ContactsIsAllowed' => false, 'ChangePasswordIsAllowed' => false, 'JsHash' => \md5(\RainLoop\Utils::GetConnectionToken()), - 'UseSieve' => $this->UseSieve(), 'UseImapThread' => (bool) $oConfig->Get('labs', 'use_imap_thread', false), 'UseImapSubscribe' => (bool) $oConfig->Get('labs', 'use_imap_list_subscribe', true), 'AllowAppendMessage' => (bool) $oConfig->Get('labs', 'allow_message_append', false), @@ -1233,6 +1276,8 @@ class Actions $aResult['LoadingDescriptionEsc'] = \htmlspecialchars($aResult['LoadingDescription'], ENT_QUOTES|ENT_IGNORE, 'UTF-8'); $oSettings = null; + $oSettingsLocal = null; + if (!$bAdmin) { $oAccount = $this->getAccountFromToken(false); @@ -1287,6 +1332,7 @@ class Actions } $oSettings = $this->SettingsProvider()->Load($oAccount); + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); } else { @@ -1457,45 +1503,54 @@ class Actions $aResult['UserBackgroundName'] = ''; $aResult['UserBackgroundHash'] = ''; - if (!$bAdmin && $oSettings instanceof \RainLoop\Settings) + if (!$bAdmin && $oSettings instanceof \RainLoop\Settings && + $oSettingsLocal instanceof \RainLoop\Settings) { if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) { $sLanguage = $oSettings->GetConf('Language', $sLanguage); } - if ($oConfig->Get('webmail', 'allow_themes', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::THEMES, $oAccount)) { $sTheme = $oSettings->GetConf('Theme', $sTheme); } - $aResult['SentFolder'] = $oSettings->GetConf('SentFolder', ''); - $aResult['DraftFolder'] = $oSettings->GetConf('DraftFolder', ''); - $aResult['SpamFolder'] = $oSettings->GetConf('SpamFolder', ''); - $aResult['TrashFolder'] = $oSettings->GetConf('TrashFolder', ''); - $aResult['ArchiveFolder'] = $oSettings->GetConf('ArchiveFolder', ''); - $aResult['NullFolder'] = $oSettings->GetConf('NullFolder', ''); + $aResult['SentFolder'] = $oSettingsLocal->GetConf('SentFolder', ''); + $aResult['DraftFolder'] = $oSettingsLocal->GetConf('DraftFolder', ''); + $aResult['SpamFolder'] = $oSettingsLocal->GetConf('SpamFolder', ''); + $aResult['TrashFolder'] = $oSettingsLocal->GetConf('TrashFolder', ''); + $aResult['ArchiveFolder'] = $oSettingsLocal->GetConf('ArchiveFolder', ''); + $aResult['NullFolder'] = $oSettingsLocal->GetConf('NullFolder', ''); + $aResult['EditorDefaultType'] = $oSettings->GetConf('EditorDefaultType', $aResult['EditorDefaultType']); $aResult['ShowImages'] = (bool) $oSettings->GetConf('ShowImages', $aResult['ShowImages']); $aResult['ContactsAutosave'] = (bool) $oSettings->GetConf('ContactsAutosave', $aResult['ContactsAutosave']); $aResult['MPP'] = (int) $oSettings->GetConf('MPP', $aResult['MPP']); $aResult['SoundNotification'] = (bool) $oSettings->GetConf('SoundNotification', $aResult['SoundNotification']); $aResult['DesktopNotifications'] = (bool) $oSettings->GetConf('DesktopNotifications', $aResult['DesktopNotifications']); - $aResult['UseThreads'] = (bool) $oSettings->GetConf('UseThreads', $aResult['UseThreads']); - $aResult['ReplySameFolder'] = (bool) $oSettings->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); $aResult['Layout'] = (int) $oSettings->GetConf('Layout', $aResult['Layout']); $aResult['UseCheckboxesInList'] = (bool) $oSettings->GetConf('UseCheckboxesInList', $aResult['UseCheckboxesInList']); - if ($oConfig->Get('webmail', 'allow_user_background', false)) + $aResult['UseThreads'] = (bool) $oSettingsLocal->GetConf('UseThreads', $aResult['UseThreads']); + $aResult['ReplySameFolder'] = (bool) $oSettingsLocal->GetConf('ReplySameFolder', $aResult['ReplySameFolder']); + + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::USER_BACKGROUND, $oAccount)) { $aResult['UserBackgroundName'] = (string) $oSettings->GetConf('UserBackgroundName', $aResult['UserBackgroundName']); $aResult['UserBackgroundHash'] = (string) $oSettings->GetConf('UserBackgroundHash', $aResult['UserBackgroundHash']); + + if (!empty($aResult['UserBackgroundHash'])) // TODO + { + $aResult['IncludeBackground'] = './?/Raw/0/Public/'.$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']); - $aResult['Signature'] = $oSettings->GetConf('Signature', $aResult['Signature']); + $aResult['DefaultIdentityID'] = $oSettingsLocal->GetConf('DefaultIdentityID', $oAccount ? $oAccount->Email() : $aResult['DefaultIdentityID']); + $aResult['DisplayName'] = $oSettingsLocal->GetConf('DisplayName', $aResult['DisplayName']); + $aResult['ReplyTo'] = $oSettingsLocal->GetConf('ReplyTo', $aResult['ReplyTo']); + $aResult['Signature'] = $oSettingsLocal->GetConf('Signature', $aResult['Signature']); + $aResult['EnableTwoFactor'] = !!$oSettings->GetConf('EnableTwoFactor', $aResult['EnableTwoFactor']); $aResult['ParentEmail'] = $oAccount->ParentEmail(); @@ -1513,8 +1568,7 @@ class Actions $sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash().$aResult['UserBackgroundHash']); $sTheme = $this->ValidateTheme($sTheme); - $sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$sStaticCache.'/Hash/'. - (empty($aResult['UserBackgroundHash']) ? '-' : $aResult['UserBackgroundHash']).'/'; + $sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$sStaticCache.'/Hash/'; $bUserLanguage = false; if (!$bAdmin && !$aResult['Auth'] && !empty($_COOKIE['rllang']) && @@ -1781,7 +1835,7 @@ class Actions // Two factor auth if ($this->TwoFactorAuthProvider()->IsActive()) { - $aData = $this->getTwoFactorInfo($oAccount->ParentEmailHelper()); + $aData = $this->getTwoFactorInfo($oAccount); if ($aData && isset($aData['IsSet'], $aData['Enable']) && !empty($aData['Secret']) && $aData['IsSet'] && $aData['Enable']) { $sSecretHash = \md5(APP_SALT.$aData['Secret'].\RainLoop\Utils::Fingerprint()); @@ -1978,8 +2032,14 @@ class Actions $oSettings = $this->SettingsProvider()->Load($oAccount); if ($oSettings) { - $oSettings->SetConf('Language', $this->ValidateLanguage($sLanguage)); - $this->SettingsProvider()->Save($oAccount, $oSettings); + $sLanguage = $this->ValidateLanguage($sLanguage); + $sCurrentLanguage = $oSettings->GetConf('Language', ''); + + if ($sCurrentLanguage !== $sLanguage) + { + $oSettings->SetConf('Language', $sLanguage); + $this->SettingsProvider()->Save($oAccount, $oSettings); + } } } @@ -1993,14 +2053,11 @@ class Actions */ public function GetAccounts($oAccount) { - $sParentEmail = $oAccount->ParentEmailHelper(); - - if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { - $sAccounts = $this->StorageProvider()->Get(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::WebmailAccounts($sParentEmail), - null + $sAccounts = $this->StorageProvider()->Get($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'accounts' ); $aAccounts = $sAccounts ? @\unserialize($sAccounts) : array(); @@ -2013,10 +2070,9 @@ class Actions } else if (1 < \count($aAccounts)) { - $sOrder = $this->StorageProvider()->Get(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::WebmailAccountsOrder($sParentEmail), - null + $sOrder = $this->StorageProvider()->Get($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'accounts_order' ); $aOrder = empty($sOrder) ? array() : @\json_decode($sOrder, true); @@ -2031,7 +2087,7 @@ class Actions } $aAccounts = array(); - if ($sParentEmail === $oAccount->Email()) + if (!$oAccount->IsAdditionalAccount()) { $aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken(); } @@ -2050,10 +2106,11 @@ class Actions if ($oAccount) { $aSubIdentities = array(); - $oSettings = $this->SettingsProvider()->Load($oAccount); - if ($oSettings) + + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); + if ($oSettingsLocal) { - $sData = $oSettings->GetConf('Identities', ''); + $sData = $oSettingsLocal->GetConf('Identities', ''); if ('' !== $sData && '[' === \substr($sData, 0, 1)) { $aSubIdentities = @\json_decode($sData, true); @@ -2093,10 +2150,11 @@ class Actions $oAccountIdentity = \RainLoop\Model\Identity::NewInstance('', $oAccount->Email()); $aSubIdentities = array(); - $oSettings = $this->SettingsProvider()->Load($oAccount); - if ($oSettings) + + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); + if ($oSettingsLocal) { - $sData = $oSettings->GetConf('Identities', ''); + $sData = $oSettingsLocal->GetConf('Identities', ''); if ('' !== $sData && '[' === \substr($sData, 0, 1)) { $aSubIdentities = @\json_decode($sData, true); @@ -2150,13 +2208,18 @@ class Actions if (!\is_array($aAccounts) || 0 >= \count($aAccounts) || (1 === \count($aAccounts) && !empty($aAccounts[$sParentEmail]))) { - $this->StorageProvider()->Clear(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::WebmailAccounts($sParentEmail)); + $this->StorageProvider()->Clear($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'accounts' + ); } else { - $this->StorageProvider()->Put(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::WebmailAccounts($sParentEmail), @\serialize($aAccounts)); + $this->StorageProvider()->Put($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'accounts', + @\serialize($aAccounts) + ); } } @@ -2168,8 +2231,8 @@ class Actions */ public function SetIdentities($oAccount, $aIdentities = array()) { - $oSettings = $this->SettingsProvider()->Load($oAccount); - if ($oSettings) + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); + if ($oSettingsLocal) { $aResult = array(); foreach ($aIdentities as $oItem) @@ -2177,8 +2240,8 @@ class Actions $aResult[] = $oItem->ToSimpleJSON(false); } - $oSettings->SetConf('Identities', @\json_encode($aResult)); - return $this->SettingsProvider()->Save($oAccount, $oSettings); + $oSettingsLocal->SetConf('Identities', @\json_encode($aResult)); + return $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal); } return false; @@ -2193,6 +2256,11 @@ class Actions { $oAccount = $this->getAccountFromToken(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FILTERS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $aFakeFilters = null; $this->Plugins() @@ -2217,6 +2285,11 @@ class Actions { $oAccount = $this->getAccountFromToken(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FILTERS, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $aIncFilters = $this->GetActionParam('Filters', array()); $sRaw = $this->GetActionParam('Raw', ''); @@ -2250,12 +2323,13 @@ class Actions */ public function DoAccountSetup() { - if (!$this->Config()->Get('webmail', 'allow_additional_accounts', true)) + $oAccount = $this->getAccountFromToken(); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); $sParentEmail = $oAccount->ParentEmailHelper(); $aAccounts = $this->GetAccounts($oAccount); @@ -2298,13 +2372,13 @@ class Actions */ public function DoAccountDelete() { - if (!$this->Config()->Get('webmail', 'allow_additional_accounts', true)) + $oAccount = $this->getAccountFromToken(); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); - $sParentEmail = $oAccount->ParentEmailHelper(); $sEmailToDelete = \trim($this->GetActionParam('EmailToDelete', '')); $sEmailToDelete = \MailSo\Base\Utils::IdnToAscii($sEmailToDelete, true); @@ -2339,13 +2413,13 @@ class Actions */ public function DoIdentityUpdate() { - if (!$this->Config()->Get('webmail', 'allow_identities', true)) + $oAccount = $this->getAccountFromToken(); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); - $sId = \trim($this->GetActionParam('Id', '')); $sEmail = \trim($this->GetActionParam('Email', '')); $sName = \trim($this->GetActionParam('Name', '')); @@ -2399,13 +2473,13 @@ class Actions */ public function DoIdentityDelete() { - if (!$this->Config()->Get('webmail', 'allow_identities', true)) + $oAccount = $this->getAccountFromToken(); + + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); - $sId = \trim($this->GetActionParam('IdToDelete', '')); if (empty($sId)) { @@ -2440,9 +2514,8 @@ class Actions return $this->FalseResponse(__FUNCTION__); } - return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::WebmailAccountsOrder($oAccount->ParentEmailHelper()), + return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_order', \json_encode($aList) )); } @@ -2457,7 +2530,7 @@ class Actions $oAccount = $this->getAccountFromToken(); $mAccounts = false; - if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { $mAccounts = $this->GetAccounts($oAccount); $mAccounts = \array_keys($mAccounts); @@ -2469,7 +2542,7 @@ class Actions } $mIdentities = false; - if ($this->Config()->Get('webmail', 'allow_identities', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) { $mIdentities = $this->GetIdentities($oAccount); } @@ -2526,7 +2599,7 @@ class Actions $bComplete = true; $aCounts = array(); - if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { $iLimit = 7; $mAccounts = $this->GetAccounts($oAccount); @@ -2572,7 +2645,7 @@ class Actions $oAccount = $this->getAccountFromToken(); $mAccounts = false; - if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { $mAccounts = $this->GetAccounts($oAccount); $mAccounts = \array_keys($mAccounts); @@ -2707,17 +2780,17 @@ class Actions { $oAccount = $this->getAccountFromToken(); - $oSettings = $this->SettingsProvider()->Load($oAccount); + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - $oSettings->SetConf('SentFolder', $this->GetActionParam('SentFolder', '')); - $oSettings->SetConf('DraftFolder', $this->GetActionParam('DraftFolder', '')); - $oSettings->SetConf('SpamFolder', $this->GetActionParam('SpamFolder', '')); - $oSettings->SetConf('TrashFolder', $this->GetActionParam('TrashFolder', '')); - $oSettings->SetConf('ArchiveFolder', $this->GetActionParam('ArchiveFolder', '')); - $oSettings->SetConf('NullFolder', $this->GetActionParam('NullFolder', '')); + $oSettingsLocal->SetConf('SentFolder', $this->GetActionParam('SentFolder', '')); + $oSettingsLocal->SetConf('DraftFolder', $this->GetActionParam('DraftFolder', '')); + $oSettingsLocal->SetConf('SpamFolder', $this->GetActionParam('SpamFolder', '')); + $oSettingsLocal->SetConf('TrashFolder', $this->GetActionParam('TrashFolder', '')); + $oSettingsLocal->SetConf('ArchiveFolder', $this->GetActionParam('ArchiveFolder', '')); + $oSettingsLocal->SetConf('NullFolder', $this->GetActionParam('NullFolder', '')); return $this->DefaultResponse(__FUNCTION__, - $this->SettingsProvider()->Save($oAccount, $oSettings)); + $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); } /** @@ -3527,10 +3600,10 @@ class Actions /** * @param string $sRepo * @param bool $bReal = false - * @param bool $bMain = true + * * @return array */ - private function getRepositoryDataByUrl($sRepo, &$bReal = false, $bMain = true) + private function getRepositoryDataByUrl($sRepo, &$bReal = false) { $bReal = false; $aRep = null; @@ -4308,13 +4381,13 @@ class Actions */ public function DoSettingsUpdate() { + $self = $this; + $oConfig = $this->Config(); + $oAccount = $this->getAccountFromToken(); $oSettings = $this->SettingsProvider()->Load($oAccount); - - $self = $this; - - $oConfig = $this->Config(); + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) { @@ -4327,7 +4400,7 @@ class Actions $oSettings->SetConf('Language', $this->ValidateLanguage($oConfig->Get('webmail', 'language', 'en'))); } - if ($oConfig->Get('webmail', 'allow_themes', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::THEMES, $oAccount)) { $this->setSettingsFromParams($oSettings, 'Theme', 'string', function ($sTheme) use ($self) { return $self->ValidateTheme($sTheme); @@ -4353,18 +4426,21 @@ class Actions $this->setSettingsFromParams($oSettings, 'ContactsAutosave', 'bool'); $this->setSettingsFromParams($oSettings, 'DesktopNotifications', 'bool'); $this->setSettingsFromParams($oSettings, 'SoundNotification', 'bool'); - $this->setSettingsFromParams($oSettings, 'UseThreads', 'bool'); - $this->setSettingsFromParams($oSettings, 'ReplySameFolder', 'bool'); $this->setSettingsFromParams($oSettings, 'UseCheckboxesInList', 'bool'); - $this->setSettingsFromParams($oSettings, 'DefaultIdentityID', 'string'); - $this->setSettingsFromParams($oSettings, 'DisplayName', 'string'); - $this->setSettingsFromParams($oSettings, 'ReplyTo', 'string'); - $this->setSettingsFromParams($oSettings, 'Signature', 'string'); $this->setSettingsFromParams($oSettings, 'EnableTwoFactor', 'bool'); + $this->setSettingsFromParams($oSettingsLocal, 'UseThreads', 'bool'); + $this->setSettingsFromParams($oSettingsLocal, 'ReplySameFolder', 'bool'); + + $this->setSettingsFromParams($oSettingsLocal, 'DefaultIdentityID', 'string'); + $this->setSettingsFromParams($oSettingsLocal, 'DisplayName', 'string'); + $this->setSettingsFromParams($oSettingsLocal, 'ReplyTo', 'string'); + $this->setSettingsFromParams($oSettingsLocal, 'Signature', 'string'); + return $this->DefaultResponse(__FUNCTION__, - $this->SettingsProvider()->Save($oAccount, $oSettings)); + $this->SettingsProvider()->Save($oAccount, $oSettings) && + $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); } /** @@ -5120,16 +5196,16 @@ class Actions $oMessage->SetXMailer('RainLoop/'.APP_VERSION); - $oSettings = $this->SettingsProvider()->Load($oAccount); + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - if ($this->Config()->Get('webmail', 'allow_identities', true)) + if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES, $oAccount)) { $oMessage->SetFrom(\MailSo\Mime\Email::Parse($sFrom)); } else { - $sDisplayName = \trim($oSettings->GetConf('DisplayName', '')); - $sReplyTo = \trim($oSettings->GetConf('ReplyTo', '')); + $sDisplayName = \trim($oSettingsLocal->GetConf('DisplayName', '')); + $sReplyTo = \trim($oSettingsLocal->GetConf('ReplyTo', '')); $oMessage->SetFrom(\MailSo\Mime\Email::NewInstance($oAccount->Email(), $sDisplayName)); @@ -5286,10 +5362,10 @@ class Actions $oMessage->SetXMailer('RainLoop/'.APP_VERSION); - $oSettings = $this->SettingsProvider()->Load($oAccount); + $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - $sDisplayName = \trim($oSettings->GetConf('DisplayName', '')); - $sReplyTo = \trim($oSettings->GetConf('ReplyTo', '')); + $sDisplayName = \trim($oSettingsLocal->GetConf('DisplayName', '')); + $sReplyTo = \trim($oSettingsLocal->GetConf('ReplyTo', '')); $oMessage->SetFrom(\MailSo\Mime\Email::NewInstance($oAccount->Email(), $sDisplayName)); @@ -5797,7 +5873,7 @@ class Actions $mResult = null; $sData = $this->StorageProvider()->Get( - $oAccount->ParentEmailHelper(), + $oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'contacts_sync' ); @@ -5840,7 +5916,7 @@ class Actions $mData = $this->getContactsSyncData($oAccount); $bResult = $this->StorageProvider()->Put( - $oAccount->ParentEmailHelper(), + $oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'contacts_sync', \RainLoop\Utils::EncodeKeyValues(array( @@ -5883,8 +5959,10 @@ class Actions return $this->TrueResponse(__FUNCTION__); } - private function getTwoFactorInfo($sEmail, $bRemoveSecret = false) + private function getTwoFactorInfo($oAccount, $bRemoveSecret = false) { + $sEmail = $oAccount->ParentEmailHelper(); + $mData = null; $aResult = array( @@ -5900,9 +5978,9 @@ class Actions { $aResult['User'] = $sEmail; - $sData = $this->StorageProvider()->Get(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::TwoFactorAuthUserData($sEmail) + $sData = $this->StorageProvider()->Get($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'two_factor' ); if ($sData) @@ -5946,21 +6024,21 @@ class Actions } /** - * @param string $sEmail + * @param \RainLoop\Model\Account $oAccount * @param string $sCode * * @return bool */ - private function removeBackupCodeFromTwoFactorInfo($sEmail, $sCode) + private function removeBackupCodeFromTwoFactorInfo($oAccount, $sCode) { - if (empty($sEmail) || empty($sCode)) + if (!$oAccount || empty($sCode)) { return false; } - $sData = $this->StorageProvider()->Get(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::TwoFactorAuthUserData($sEmail) + $sData = $this->StorageProvider()->Get($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'two_factor' ); if ($sData) @@ -5974,9 +6052,9 @@ class Actions $mData['BackupCodes'] = \trim(\preg_replace('/[^\d]+/', ' ', $sBackupCodes)); - return $this->StorageProvider()->Put(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::TwoFactorAuthUserData($sEmail), + return $this->StorageProvider()->Put($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'two_factor', \RainLoop\Utils::EncodeKeyValues($mData) ); } @@ -5990,15 +6068,16 @@ class Actions */ public function DoGetTwoFactorInfo() { - if (!$this->TwoFactorAuthProvider()->IsActive()) + $oAccount = $this->getAccountFromToken(); + + if (!$this->TwoFactorAuthProvider()->IsActive() || + !$this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); - return $this->DefaultResponse(__FUNCTION__, - $this->getTwoFactorInfo($oAccount->ParentEmailHelper(), true)); + $this->getTwoFactorInfo($oAccount, true)); } /** @@ -6006,12 +6085,14 @@ class Actions */ public function DoCreateTwoFactorSecret() { - if (!$this->TwoFactorAuthProvider()->IsActive()) + $oAccount = $this->getAccountFromToken(); + + if (!$this->TwoFactorAuthProvider()->IsActive() || + !$this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); $sEmail = $oAccount->ParentEmailHelper(); $sSecret = $this->TwoFactorAuthProvider()->CreateSecret(); @@ -6022,9 +6103,9 @@ class Actions $aCodes[] = \rand(100000000, 900000000); } - $this->StorageProvider()->Put(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::TwoFactorAuthUserData($sEmail), + $this->StorageProvider()->Put($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'two_factor', \RainLoop\Utils::EncodeKeyValues(array( 'User' => $sEmail, 'Enable' => false, @@ -6035,7 +6116,7 @@ class Actions \sleep(1); return $this->DefaultResponse(__FUNCTION__, - $this->getTwoFactorInfo($sEmail)); + $this->getTwoFactorInfo($oAccount)); } /** @@ -6043,15 +6124,15 @@ class Actions */ public function DoShowTwoFactorSecret() { - if (!$this->TwoFactorAuthProvider()->IsActive()) + $oAccount = $this->getAccountFromToken(); + + if (!$this->TwoFactorAuthProvider()->IsActive() || + !$this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); - $sEmail = $oAccount->ParentEmailHelper(); - - $aResult = $this->getTwoFactorInfo($sEmail); + $aResult = $this->getTwoFactorInfo($oAccount); if (\is_array($aResult)) { unset($aResult['BackupCodes']); @@ -6065,21 +6146,23 @@ class Actions */ public function DoEnableTwoFactor() { - if (!$this->TwoFactorAuthProvider()->IsActive()) + $oAccount = $this->getAccountFromToken(); + + if (!$this->TwoFactorAuthProvider()->IsActive() || + !$this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); $sEmail = $oAccount->ParentEmailHelper(); $bResult = false; - $mData = $this->getTwoFactorInfo($sEmail); + $mData = $this->getTwoFactorInfo($oAccount); if (isset($mData['Secret'], $mData['BackupCodes'])) { - $bResult = $this->StorageProvider()->Put(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::TwoFactorAuthUserData($sEmail), + $bResult = $this->StorageProvider()->Put($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'two_factor', \RainLoop\Utils::EncodeKeyValues(array( 'User' => $sEmail, 'Enable' => '1' === \trim($this->GetActionParam('Enable', '0')), @@ -6097,20 +6180,21 @@ class Actions */ public function DoTestTwoFactorInfo() { - if (!$this->TwoFactorAuthProvider()->IsActive()) + $oAccount = $this->getAccountFromToken(); + + if (!$this->TwoFactorAuthProvider()->IsActive() || + !$this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); - $sCode = \trim($this->GetActionParam('Code', '')); - $oData = $this->getTwoFactorInfo($oAccount->ParentEmailHelper()); - $sSecret = !empty($oData['Secret']) ? $oData['Secret'] : ''; + $aData = $this->getTwoFactorInfo($oAccount); + $sSecret = !empty($aData['Secret']) ? $aData['Secret'] : ''; $this->Logger()->WriteDump(array( - $sCode, $sSecret, $oData, + $sCode, $sSecret, $aData, $this->TwoFactorAuthProvider()->VerifyCode($sSecret, $sCode) )); @@ -6124,20 +6208,21 @@ class Actions */ public function DoClearTwoFactorInfo() { - if (!$this->TwoFactorAuthProvider()->IsActive()) + $oAccount = $this->getAccountFromToken(); + + if (!$this->TwoFactorAuthProvider()->IsActive() || + !$this->GetCapa(false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount)) { return $this->FalseResponse(__FUNCTION__); } - $oAccount = $this->getAccountFromToken(); - - $this->StorageProvider()->Clear(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::TwoFactorAuthUserData($oAccount->ParentEmailHelper()) + $this->StorageProvider()->Clear($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, + 'two_factor' ); return $this->DefaultResponse(__FUNCTION__, - $this->getTwoFactorInfo($oAccount->ParentEmailHelper(), true)); + $this->getTwoFactorInfo($oAccount, true)); } /** @@ -6867,6 +6952,11 @@ class Actions { $oAccount = $this->getAccountFromToken(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::USER_BACKGROUND, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $oSettings = $this->SettingsProvider()->Load($oAccount); if ($oAccount && $oSettings) { @@ -6883,7 +6973,8 @@ class Actions $oSettings->SetConf('UserBackgroundHash', ''); } - return $this->DefaultResponse(__FUNCTION__, $oAccount && $oSettings ? $this->SettingsProvider()->Save($oAccount, $oSettings) : false); + return $this->DefaultResponse(__FUNCTION__, $oAccount && $oSettings ? + $this->SettingsProvider()->Save($oAccount, $oSettings) : false); } /** @@ -6893,6 +6984,11 @@ class Actions { $oAccount = $this->getAccountFromToken(); + if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::USER_BACKGROUND, $oAccount)) + { + return $this->FalseResponse(__FUNCTION__); + } + $sName = ''; $sHash = ''; @@ -7027,7 +7123,7 @@ class Actions $sFileStart = \trim($sFileStart); if (false !== \strpos($sFileStart, 'BEGIN:VCARD')) { - $mResponse = $this->importContactsFromVcfFile($oAccount, $mData, $sFileStart); + $mResponse = $this->importContactsFromVcfFile($oAccount, $mData); } else if (false !== \strpos($sFileStart, ',') || false !== \strpos($sFileStart, ';')) { @@ -7125,11 +7221,10 @@ class Actions /** * @param \RainLoop\Model\Account $oAccount * @param resource $rFile - * @param string $sFileStart * * @return int */ - private function importContactsFromVcfFile($oAccount, $rFile, $sFileStart) + private function importContactsFromVcfFile($oAccount, $rFile) { $iCount = 0; if ($oAccount && \is_resource($rFile)) @@ -7265,7 +7360,7 @@ class Actions /** * @param bool $bAdmin - * @param \RainLoop\Model\Account $oAccount + * @param \RainLoop\Model\Account $oAccount = null * * @return array */ @@ -7275,8 +7370,9 @@ class Actions $aResult = array(); - if ($this->UseSieve()) + if ($oConfig->Get('capa', 'filters', false)) { + $aResult[] = \RainLoop\Enumerations\Capa::FILTERS; if ($bAdmin || ($oAccount && $oAccount->Domain()->UseSieve())) { $aResult[] = \RainLoop\Enumerations\Capa::SIEVE; @@ -7293,7 +7389,8 @@ class Actions $aResult[] = \RainLoop\Enumerations\Capa::ADDITIONAL_IDENTITIES; } - if ($oConfig->Get('security', 'allow_two_factor_auth', false)) + if ($oConfig->Get('security', 'allow_two_factor_auth', false) && + ($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount()))) { $aResult[] = \RainLoop\Enumerations\Capa::TWO_FACTOR; } @@ -7334,12 +7431,13 @@ class Actions /** * @param bool $bAdmin * @param string $sName + * @param \RainLoop\Model\Account $oAccount = null * * @return bool */ - public function GetCapa($bAdmin, $sName) + public function GetCapa($bAdmin, $sName, $oAccount = null) { - return \in_array($sName, $this->Capa($bAdmin)); + return \in_array($sName, $this->Capa($bAdmin, $oAccount)); } /** @@ -8266,11 +8364,11 @@ class Actions public function GetLanguageAndTheme() { $oAccount = $this->GetAccount(); - $oSettings = $oAccount instanceof \RainLoop\Model\Account ? $this->SettingsProvider()->Load($oAccount) : null; $sLanguage = $this->Config()->Get('webmail', 'language', 'en'); $sTheme = $this->Config()->Get('webmail', 'theme', 'Default'); + $oSettings = $oAccount instanceof \RainLoop\Model\Account ? $this->SettingsProvider()->Load($oAccount) : null; if ($oSettings instanceof \RainLoop\Settings) { $sLanguage = $oSettings->GetConf('Language', $sLanguage); diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php index 13b3d7e21..4d2e23cf8 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Api.php @@ -169,27 +169,9 @@ class Api $oStorageProvider = \RainLoop\Api::Actions()->StorageProvider(); if ($oStorageProvider && $oStorageProvider->IsActive()) { - // TwoFactor Auth User Data - $oStorageProvider->Clear(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::TwoFactorAuthUserData($sEmail) - ); - - // Accounts list - $oStorageProvider->Clear(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - \RainLoop\KeyPathHelper::WebmailAccounts($sEmail) - ); - - // Contact sync data - $oStorageProvider->Clear($sEmail, - \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, - 'contacts_sync' - ); + $oStorageProvider->DeleteStorage($sEmail); } - \RainLoop\Api::Actions()->SettingsProvider()->ClearByEmail($sEmail); - if (\RainLoop\Api::Actions()->AddressBookProvider() && \RainLoop\Api::Actions()->AddressBookProvider()->IsActive()) { diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php index de98ef967..b0d731c8f 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Enumerations/Capa.php @@ -12,6 +12,7 @@ class Capa const THEMES = 'THEMES'; const USER_BACKGROUND = 'USER_BACKGROUND'; const SIEVE = 'SIEVE'; + const FILTERS = 'FILTERS'; const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS'; const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS'; const ADDITIONAL_IDENTITIES = 'ADDITIONAL_IDENTITIES'; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php b/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php index b2d5242b1..7b9d7808a 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php @@ -4,36 +4,6 @@ namespace RainLoop; class KeyPathHelper { - /** - * @param string $sEmail - * - * @return string - */ - static public function TwoFactorAuthUserData($sEmail) - { - return 'TwoFactorAuth/User/'.$sEmail.'/Data/'; - } - - /** - * @param string $sEmail - * - * @return string - */ - static public function WebmailAccounts($sEmail) - { - return 'Webmail/Accounts/'.$sEmail.'/Array'; - } - - /** - * @param string $sEmail - * - * @return string - */ - static public function WebmailAccountsOrder($sEmail) - { - return 'Webmail/AccountsSortOrder/'.$sEmail.'/Array'; - } - /** * @param string $sHash * @@ -161,13 +131,13 @@ class KeyPathHelper /** * @param string $sTheme - * @param string $sPluginsHash + * @param string $sHash * @param string $sPublickHash * * @return string */ - static public function CssCache($sTheme, $sPluginsHash, $sPublickHash = '') + static public function CssCache($sTheme, $sHash) { - return '/CssCache/'.$sPluginsHash.'/'.$sPublickHash.'/'.$sTheme.'/'.APP_VERSION.'/'; + return '/CssCache/'.$sHash.'/'.$sTheme.'/'.APP_VERSION.'/'; } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php index b997dedd5..82c463685 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php @@ -125,6 +125,14 @@ class Account extends \RainLoop\Account // for backward compatibility return 0 < \strlen($this->sParentEmail) ? $this->sParentEmail : $this->sEmail; } + /** + * @return string + */ + public function IsAdditionalAccount() + { + return 0 < \strlen($this->sParentEmail); + } + /** * @return string */ diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php index 10fd3239a..d3b7844d2 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files/DefaultStorage.php @@ -71,7 +71,7 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface { $mResult = @\fopen($sFileName, $sOpenMode); } - + return $mResult; } @@ -107,7 +107,7 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface { $mResult = @\unlink($sFileName); } - + return $mResult; } @@ -125,7 +125,7 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface { $mResult = \filesize($sFileName); } - + return $mResult; } @@ -165,13 +165,28 @@ class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface */ private function generateFileName($oAccount, $sKey, $bMkDir = false) { - $sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', - ('' === $oAccount->ParentEmail() ? '' : $oAccount->ParentEmail().'/').$oAccount->Email()); + $sEmail = $sSubEmail = ''; + if ($oAccount instanceof \RainLoop\Model\Account) + { + $sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $oAccount->ParentEmailHelper()); + if ($oAccount->IsAdditionalAccount()) + { + $sSubEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $oAccount->Email()); + } + } + + if (empty($sEmail)) + { + $sEmail = '__unknown__'; + } $sKeyPath = \sha1($sKey); $sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath; - $sFilePath = $this->sDataPath.'/'.rtrim(substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'.$sKeyPath; + $sFilePath = $this->sDataPath.'/'. + \str_pad(\rtrim(\substr($sEmail, 0, 2), '@'), 2, '_').'/'.$sEmail.'/'. + (0 < \strlen($sSubEmail) ? $sSubEmail.'/' : ''). + $sKeyPath; if ($bMkDir && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath))) { diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php index 31740fb44..31180f14f 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings.php @@ -42,16 +42,6 @@ class Settings extends \RainLoop\Providers\AbstractProvider return $this->oDriver->Save($oAccount, $oSettings->DataAsArray()); } - /** - * @param string $sEmail - * - * @return bool - */ - public function ClearByEmail($sEmail) - { - return $this->oDriver->ClearByEmail($sEmail); - } - /** * @return bool */ diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php index 95eec2ec1..032df1ecf 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php @@ -5,6 +5,7 @@ namespace RainLoop\Providers\Settings; class DefaultSettings implements \RainLoop\Providers\Settings\SettingsInterface { const FILE_NAME = 'settings'; + const FILE_NAME_LOCAL = 'settings_local'; /** * @var \RainLoop\Providers\Storage @@ -28,7 +29,10 @@ class DefaultSettings implements \RainLoop\Providers\Settings\SettingsInterface { $sValue = $this->oStorageProvider->Get($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, - \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME); + $this->oStorageProvider->IsLocal() ? + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME_LOCAL : + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME + ); $aSettings = array(); if (\is_string($sValue)) @@ -53,19 +57,23 @@ class DefaultSettings implements \RainLoop\Providers\Settings\SettingsInterface { return $this->oStorageProvider->Put($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, - \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME, + $this->oStorageProvider->IsLocal() ? + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME_LOCAL : + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME, \json_encode($aSettings)); } /** - * @param string $sEmail + * @param \RainLoop\Model\Account $oAccount * * @return bool */ - public function ClearByEmail($sEmail) + public function Delete($oAccount) { - return $this->oStorageProvider->Clear($sEmail, + return $this->oStorageProvider->Clear($oAccount, \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, - \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME); + $this->oStorageProvider->IsLocal() ? + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME_LOCAL : + \RainLoop\Providers\Settings\DefaultSettings::FILE_NAME); } } \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php index 91eba8e46..dba0e83e1 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php @@ -20,9 +20,9 @@ interface SettingsInterface public function Save($oAccount, array $aSettings); /** - * @param string $sEmail + * @param \RainLoop\Model\Account $oAccount * * @return bool */ - public function ClearByEmail($sEmail); + public function Delete($oAccount); } \ No newline at end of file diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php index f3bfa88e4..6a0b4d55c 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage.php @@ -18,15 +18,15 @@ class Storage extends \RainLoop\Providers\AbstractProvider } /** - * @param \RainLoop\Model\Account|string|null $oAccount + * @param \RainLoop\Model\Account|string|null $mAccount * @param int $iStorageType * * @return bool */ - public function verifyAccount($oAccount, $iStorageType) + private function verifyAccount($mAccount, $iStorageType) { if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType && - !($oAccount instanceof \RainLoop\Model\Account || \is_string($oAccount))) + !($mAccount instanceof \RainLoop\Model\Account || \is_string($mAccount))) { return false; } @@ -83,10 +83,20 @@ class Storage extends \RainLoop\Providers\AbstractProvider { return false; } - + return $this->oDriver->Clear($oAccount, $iStorageType, $sKey); } + /** + * @param \RainLoop\Model\Account|string $oAccount + * + * @return bool + */ + public function DeleteStorage($oAccount) + { + return $this->oDriver->DeleteStorage($oAccount); + } + /** * @return bool */ @@ -94,4 +104,13 @@ class Storage extends \RainLoop\Providers\AbstractProvider { return $this->oDriver instanceof \RainLoop\Providers\Storage\StorageInterface; } + + /** + * @return bool + */ + public function IsLocal() + { + return $this->oDriver instanceof \RainLoop\Providers\Storage\StorageInterface && + $this->oDriver->IsLocal(); + } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php index 7bf9e871a..a7e30f030 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php @@ -9,14 +9,21 @@ class DefaultStorage implements \RainLoop\Providers\Storage\StorageInterface */ private $sDataPath; + /** + * @var bool + */ + private $bLocal; + /** * @param string $sStoragePath + * @param bool $bLocal = false * * @return void */ - public function __construct($sStoragePath) + public function __construct($sStoragePath, $bLocal = false) { $this->sDataPath = \rtrim(\trim($sStoragePath), '\\/'); + $this->bLocal = !!$bLocal; } /** @@ -49,7 +56,7 @@ class DefaultStorage implements \RainLoop\Providers\Storage\StorageInterface { $mValue = \file_get_contents($sFileName); } - + return false === $mValue ? $mDefault : $mValue; } @@ -68,33 +75,78 @@ class DefaultStorage implements \RainLoop\Providers\Storage\StorageInterface { $mResult = @\unlink($sFileName); } - + return $mResult; } + /** + * @param \RainLoop\Model\Account|string $oAccount + * + * @return bool + */ + public function DeleteStorage($oAccount) + { + $sPath = $this->generateFileName($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::USER, 'xxx', false, true); + + if (!empty($sPath) && \is_dir($sPath)) + { + \MailSo\Base\Utils::RecRmDir($sPath); + } + + $sPath = $this->generateFileName($oAccount, + \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'xxx', false, true); + + if (!empty($sPath) && \is_dir($sPath)) + { + \MailSo\Base\Utils::RecRmDir($sPath); + } + + return true; + } + + /** + * @return bool + */ + public function IsLocal() + { + return $this->bLocal; + } + /** * @param \RainLoop\Model\Account|string|null $mAccount * @param int $iStorageType * @param string $sKey * @param bool $bMkDir = false + * @param bool $bForDeleteAction = false * * @return string */ - private function generateFileName($mAccount, $iStorageType, $sKey, $bMkDir = false) + private function generateFileName($mAccount, $iStorageType, $sKey, $bMkDir = false, $bForDeleteAction = false) { if (null === $mAccount) { $iStorageType = \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY; } - $sEmail = $mAccount instanceof \RainLoop\Model\Account ? \preg_replace('/[^a-z0-9\-\.@]+/', '_', - ('' === $mAccount->ParentEmail() ? '' : $mAccount->ParentEmail().'/').$mAccount->Email()) : ''; + $sEmail = $sSubEmail = ''; + if ($mAccount instanceof \RainLoop\Model\Account) + { + $sEmail = $mAccount->ParentEmailHelper(); + if ($this->bLocal && $mAccount->IsAdditionalAccount() && !$bForDeleteAction) + { + $sSubEmail = $mAccount->Email(); + } + } if (\is_string($mAccount) && empty($sEmail)) { - $sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $mAccount); + $sEmail = $mAccount; } + $sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $sEmail); + $sSubEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $sSubEmail); + $sTypePath = $sKeyPath = ''; switch ($iStorageType) { @@ -118,10 +170,13 @@ class DefaultStorage implements \RainLoop\Providers\Storage\StorageInterface } else if (!empty($sEmail)) { - $sFilePath = $this->sDataPath.'/'.$sTypePath.'/'.rtrim(substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'.$sKeyPath; + $sFilePath = $this->sDataPath.'/'.$sTypePath.'/'. + \str_pad(\rtrim(\substr($sEmail, 0, 2), '@'), 2, '_').'/'.$sEmail.'/'. + (0 < \strlen($sSubEmail) ? $sSubEmail.'/' : ''). + ($bForDeleteAction ? '' : $sKeyPath); } - if ($bMkDir && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath))) + if ($bMkDir && !$bForDeleteAction && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath))) { if (!@\mkdir(\dirname($sFilePath), 0755, true)) { diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/StorageInterface.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/StorageInterface.php index 8922d3018..a3d7f87f0 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/StorageInterface.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Storage/StorageInterface.php @@ -32,4 +32,9 @@ interface StorageInterface * @return bool */ public function Clear($oAccount, $iStorageType, $sKey); + + /** + * @return bool + */ + public function IsLocal(); } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index 572278ee6..dc1776a66 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -620,7 +620,6 @@ class ServiceActions $bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2]; $bJson = !empty($this->aPaths[9]) && 'Json' === $this->aPaths[9]; - $sHash = !empty($this->aPaths[8]) && 5 < \strlen($this->aPaths[8]) ? $this->aPaths[8] : ''; if ($bJson) { @@ -652,7 +651,7 @@ class ServiceActions $sCacheFileName = ''; if ($bCacheEnabled) { - $sCacheFileName = \RainLoop\KeyPathHelper::CssCache($sTheme, $this->oActions->Plugins()->Hash(), $sHash); + $sCacheFileName = \RainLoop\KeyPathHelper::CssCache($sTheme, $this->oActions->Plugins()->Hash()); $sResult = $this->Cacher()->Get($sCacheFileName); } @@ -691,15 +690,6 @@ 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)) @@ -1034,7 +1024,9 @@ class ServiceActions */ public function ServiceChange() { - if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + $oAccount = $this->oActions->GetAccount(); + + if ($oAccount && $this->oActions->GetCapa(false, \RainLoop\Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) { $oAccountToLogin = null; $sEmail = empty($this->aPaths[2]) ? '' : \urldecode(\trim($this->aPaths[2])); @@ -1042,14 +1034,10 @@ class ServiceActions { $sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail); - $oAccount = $this->oActions->GetAccount(); - if ($oAccount) + $aAccounts = $this->oActions->GetAccounts($oAccount); + if (isset($aAccounts[$sEmail])) { - $aAccounts = $this->oActions->GetAccounts($oAccount); - if (isset($aAccounts[$sEmail])) - { - $oAccountToLogin = $this->oActions->GetAccountFromCustomToken($aAccounts[$sEmail], false, false); - } + $oAccountToLogin = $this->oActions->GetAccountFromCustomToken($aAccounts[$sEmail], false, false); } } diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Settings.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Settings.php index ef1bfdcee..d234f0833 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Settings.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Settings.php @@ -9,12 +9,18 @@ class Settings */ protected $aData; + /** + * @var bool + */ + protected $bLocal; + /** * @return void */ - public function __construct() + public function __construct($bLocal = false) { $this->aData = array(); + $this->bLocal = !!$bLocal; } /** @@ -40,6 +46,14 @@ class Settings return $this->aData; } + /** + * @return bool + */ + public function IsLocal() + { + return $this->bLocal; + } + /** * @param string $sName * @param mixed $mDefValue = null diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php index 8dea13ee0..21ff4d6ae 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Social.php @@ -196,6 +196,7 @@ class Social $oSettings->SetConf('GoogleAccessToken', ''); $oSettings->SetConf('GoogleSocialName', ''); + return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); } @@ -260,6 +261,7 @@ class Social $oSettings->SetConf('TwitterAccessToken', ''); $oSettings->SetConf('TwitterSocialName', ''); + return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings); }