diff --git a/dev/Common/Links.js b/dev/Common/Links.js index 4d9abfd6c..980e14e88 100644 --- a/dev/Common/Links.js +++ b/dev/Common/Links.js @@ -237,13 +237,6 @@ export function staticPrefix(path) { return VERSION_PREFIX + 'static/' + path; } -/** - * @returns {string} - */ -export function emptyContactPic() { - return staticPrefix('css/images/empty-contact.png'); -} - /** * @param {string} fileName * @returns {string} diff --git a/dev/Knoin/AbstractModel.js b/dev/Knoin/AbstractModel.js index 1895703c4..3cb7b0f15 100644 --- a/dev/Knoin/AbstractModel.js +++ b/dev/Knoin/AbstractModel.js @@ -13,12 +13,10 @@ export class AbstractModel { */ constructor() { /* - constructor(props) { if (new.target === Parent) { throw new Error("Can't instantiate abstract class!"); } this.sModelName = new.target.name; - props && Object.entries(props).forEach(([key, value]) => '@' !== key[0] && (this[key] = value)); */ } @@ -59,7 +57,8 @@ export class AbstractModel { // Object/Folder // Object/Message // Object/Template - return this.validJson(json) ? new this(json) : null; + return this.validJson(json) ? new this() : null; +// json && Object.entries(json).forEach(([key, value]) => '@' !== key[0] && (this[key] = value)); } } diff --git a/dev/Model/Contact.js b/dev/Model/Contact.js index 39242db31..5080c60de 100644 --- a/dev/Model/Contact.js +++ b/dev/Model/Contact.js @@ -2,7 +2,6 @@ import ko from 'ko'; import { ContactPropertyType } from 'Common/Enums'; import { pInt, pString } from 'Common/Utils'; -import { emptyContactPic } from 'Common/Links'; import { AbstractModel } from 'Knoin/AbstractModel'; @@ -10,7 +9,7 @@ class ContactModel extends AbstractModel { constructor() { super(); - this.idContact = 0; + this.id = 0; this.display = ''; this.properties = []; this.readOnly = false; @@ -53,11 +52,11 @@ class ContactModel extends AbstractModel { static reviveFromJson(json) { const contact = super.reviveFromJson(json); if (contact) { - contact.idContact = pInt(json.IdContact); - contact.display = pString(json.Display); - contact.readOnly = !!json.ReadOnly; + contact.id = pInt(json.id); + contact.display = pString(json.display); + contact.readOnly = !!json.readOnly; - if (Array.isNotEmpty(json.Properties)) { + if (Array.isNotEmpty(json.properties)) { json.Properties.forEach(property => { if (property && property.Type && null != property.Value && null != property.TypeStr) { contact.properties.push([pInt(property.Type), pString(property.Value), pString(property.TypeStr)]); @@ -68,18 +67,11 @@ class ContactModel extends AbstractModel { return contact; } - /** - * @returns {string} - */ - srcAttr() { - return emptyContactPic(); - } - /** * @returns {string} */ generateUid() { - return pString(this.idContact); + return pString(this.id); } /** diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js index e97e74cb2..f8db23177 100644 --- a/dev/View/Popup/Contacts.js +++ b/dev/View/Popup/Contacts.js @@ -155,7 +155,7 @@ class ContactsPopupView extends AbstractViewNext { }); this.contactsCheckedOrSelectedUids = ko.computed(() => - this.contactsCheckedOrSelected().map(contact => contact.idContact) + this.contactsCheckedOrSelected().map(contact => contact.id) ); this.selector = new Selector( @@ -436,7 +436,7 @@ class ContactsPopupView extends AbstractViewNext { if (contacts.length) { contacts.forEach(contact => { - if (currentContact && currentContact.idContact === contact.idContact) { + if (currentContact && currentContact.id === contact.id) { currentContact = null; this.currentContact(null); } @@ -500,7 +500,7 @@ class ContactsPopupView extends AbstractViewNext { this.viewReadOnly(false); if (contact) { - id = contact.idContact; + id = contact.id; if (Array.isNotEmpty(contact.properties)) { contact.properties.forEach(property => { if (property && property[0]) { diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php index dc4a302bd..0df1c2ea1 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php @@ -15,7 +15,7 @@ namespace MailSo\Mime; * @category MailSo * @package Mime */ -class Email +class Email implements \JsonSerializable { /** * @var string @@ -253,4 +253,15 @@ class Email return \trim($sReturn); } + + public function jsonSerialize() + { + return array( + '@Object' => 'Object/Email', + 'Name' => \MailSo\Base\Utils::Utf8Clear($this->GetDisplayName()), + 'Email' => \MailSo\Base\Utils::Utf8Clear($this->GetEmail(true)), + 'DkimStatus' => $this->GetDkimStatus(), + 'DkimValue' => $this->GetDkimValue() + ); + } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 6834f9339..95a09bf65 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -8,6 +8,8 @@ use RainLoop\Enumerations\UploadClientError; class Actions { use Actions\Admin; + use Actions\User; + use Actions\Response; const AUTH_TFA_SIGN_ME_TOKEN_KEY = 'rltfasmauth'; const AUTH_SIGN_ME_TOKEN_KEY = 'rlsmauth'; @@ -1850,74 +1852,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return \MailSo\Base\Utils::Md5Rand(APP_SALT.$sEmail); } - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoLogin() : array - { - $sEmail = \MailSo\Base\Utils::Trim($this->GetActionParam('Email', '')); - $sPassword = $this->GetActionParam('Password', ''); - $sLanguage = $this->GetActionParam('Language', ''); - $bSignMe = '1' === (string) $this->GetActionParam('SignMe', '0'); - - $sAdditionalCode = $this->GetActionParam('AdditionalCode', ''); - $bAdditionalCodeSignMe = '1' === (string) $this->GetActionParam('AdditionalCodeSignMe', '0'); - - $oAccount = null; - - $this->Logger()->AddSecret($sPassword); - - if ('sleep@sleep.dev' === $sEmail && 0 < \strlen($sPassword) && - \is_numeric($sPassword) && $this->Config()->Get('debug', 'enable', false) && - 0 < (int) $sPassword && 30 > (int) $sPassword - ) - { - \sleep((int) $sPassword); - throw new Exceptions\ClientException(Notifications::AuthError); - } - - try - { - $oAccount = $this->LoginProcess($sEmail, $sPassword, - $bSignMe ? $this->generateSignMeToken($sEmail) : '', - $sAdditionalCode, $bAdditionalCodeSignMe); - } - catch (Exceptions\ClientException $oException) - { - if ($oException && - Notifications::AccountTwoFactorAuthRequired === $oException->getCode()) - { - return $this->DefaultResponse(__FUNCTION__, true, array( - 'TwoFactorAuth' => true - )); - } - else - { - throw $oException; - } - } - - $this->AuthToken($oAccount); - - if ($oAccount && 0 < \strlen($sLanguage)) - { - $oSettings = $this->SettingsProvider()->Load($oAccount); - if ($oSettings) - { - $sLanguage = $this->ValidateLanguage($sLanguage); - $sCurrentLanguage = $oSettings->GetConf('Language', ''); - - if ($sCurrentLanguage !== $sLanguage) - { - $oSettings->SetConf('Language', $sLanguage); - $this->SettingsProvider()->Save($oAccount, $oSettings); - } - } - } - - return $this->TrueResponse(__FUNCTION__); - } - public function GetAccounts(Model\Account $oAccount) : array { if ($this->GetCapa(false, false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) @@ -2172,7 +2106,7 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut continue; } - $aResult[] = $oItem->ToSimpleJSON(false); + $aResult[] = $oItem->ToSimpleJSON(); } return $this->StorageProvider(true)->Put($oAccount, @@ -2187,7 +2121,7 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut $aResult = array(); foreach ($aTemplates as $oItem) { - $aResult[] = $oItem->ToSimpleJSON(false); + $aResult[] = $oItem->ToSimpleJSON(); } return $this->StorageProvider(true)->Put($oAccount, @@ -2197,517 +2131,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut ); } - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoFilters() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::FILTERS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $aFakeFilters = null; - - $this->Plugins() - ->RunHook('filter.filters-fake', array($oAccount, &$aFakeFilters)) - ; - - if ($aFakeFilters) - { - return $this->DefaultResponse(__FUNCTION__, $aFakeFilters); - } - - return $this->DefaultResponse(__FUNCTION__, - $this->FiltersProvider()->Load($oAccount, $oAccount->DomainSieveAllowRaw())); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoFiltersSave() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::FILTERS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $aIncFilters = $this->GetActionParam('Filters', array()); - - $sRaw = $this->GetActionParam('Raw', ''); - $bRawIsActive = '1' === (string) $this->GetActionParam('RawIsActive', '0'); - - $aFilters = array(); - foreach ($aIncFilters as $aFilter) - { - if (is_array($aFilter)) - { - $oFilter = new Providers\Filters\Classes\Filter(); - if ($oFilter->FromJSON($aFilter)) - { - $aFilters[] = $oFilter; - } - } - } - - $this->Plugins() - ->RunHook('filter.filters-save', array($oAccount, &$aFilters, &$sRaw, &$bRawIsActive)) - ; - - return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->Save($oAccount, - $aFilters, $sRaw, $bRawIsActive)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoAccountSetup() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sParentEmail = $oAccount->ParentEmailHelper(); - - $aAccounts = $this->GetAccounts($oAccount); - - $sEmail = \trim($this->GetActionParam('Email', '')); - $sPassword = $this->GetActionParam('Password', ''); - $bNew = '1' === (string) $this->GetActionParam('New', '1'); - - $sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true); - if ($bNew && ($oAccount->Email() === $sEmail || $sParentEmail === $sEmail || isset($aAccounts[$sEmail]))) - { - throw new Exceptions\ClientException(Notifications::AccountAlreadyExists); - } - else if (!$bNew && !isset($aAccounts[$sEmail])) - { - throw new Exceptions\ClientException(Notifications::AccountDoesNotExist); - } - - $oNewAccount = $this->LoginProcess($sEmail, $sPassword, '', '', false, true); - $oNewAccount->SetParentEmail($sParentEmail); - - $aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken(); - if (!$oAccount->IsAdditionalAccount()) - { - $aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken(); - } - - $this->SetAccounts($oAccount, $aAccounts); - return $this->TrueResponse(__FUNCTION__); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoAccountDelete() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sParentEmail = $oAccount->ParentEmailHelper(); - $sEmailToDelete = \trim($this->GetActionParam('EmailToDelete', '')); - $sEmailToDelete = \MailSo\Base\Utils::IdnToAscii($sEmailToDelete, true); - - $aAccounts = $this->GetAccounts($oAccount); - - if (0 < \strlen($sEmailToDelete) && $sEmailToDelete !== $sParentEmail && isset($aAccounts[$sEmailToDelete])) - { - unset($aAccounts[$sEmailToDelete]); - - $oAccountToChange = null; - if ($oAccount->Email() === $sEmailToDelete && !empty($aAccounts[$sParentEmail])) - { - $oAccountToChange = $this->GetAccountFromCustomToken($aAccounts[$sParentEmail], false, false); - if ($oAccountToChange) - { - $this->AuthToken($oAccountToChange); - } - } - - $this->SetAccounts($oAccount, $aAccounts); - return $this->TrueResponse(__FUNCTION__, array('Reload' => !!$oAccountToChange)); - } - - return $this->FalseResponse(__FUNCTION__); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoAttachmentsActions() : array - { - if (!$this->GetCapa(false, false, Enumerations\Capa::ATTACHMENTS_ACTIONS)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $oAccount = $this->initMailClientConnection(); - - $sAction = $this->GetActionParam('Do', ''); - $aHashes = $this->GetActionParam('Hashes', null); - - $mResult = false; - $bError = false; - $aData = false; - - if (\is_array($aHashes) && 0 < \count($aHashes)) - { - $aData = array(); - foreach ($aHashes as $sZipHash) - { - $aResult = $this->getMimeFileByHash($oAccount, $sZipHash); - if (!empty($aResult['FileHash'])) - { - $aData[] = $aResult; - } - else - { - $bError = true; - break; - } - } - } - - $oFilesProvider = $this->FilesProvider(); - if (!empty($sAction) && !$bError && \is_array($aData) && 0 < \count($aData) && - $oFilesProvider && $oFilesProvider->IsActive()) - { - $bError = false; - switch (\strtolower($sAction)) - { - case 'zip': - - if (\class_exists('ZipArchive')) - { - $sZipHash = \MailSo\Base\Utils::Md5Rand(); - $sZipFileName = $oFilesProvider->GenerateLocalFullFileName($oAccount, $sZipHash); - - if (!empty($sZipFileName)) - { - $oZip = new \ZipArchive(); - $oZip->open($sZipFileName, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE); - $oZip->setArchiveComment('SnappyMail/'.APP_VERSION); - - foreach ($aData as $aItem) - { - $sFileName = (string) (isset($aItem['FileName']) ? $aItem['FileName'] : 'file.dat'); - $sFileHash = (string) (isset($aItem['FileHash']) ? $aItem['FileHash'] : ''); - - if (!empty($sFileHash)) - { - $sFullFileNameHash = $oFilesProvider->GetFileName($oAccount, $sFileHash); - if (!$oZip->addFile($sFullFileNameHash, $sFileName)) - { - $bError = true; - } - } - } - - if (!$bError) - { - $bError = !$oZip->close(); - } - else - { - $oZip->close(); - } - } - - foreach ($aData as $aItem) - { - $sFileHash = (string) (isset($aItem['FileHash']) ? $aItem['FileHash'] : ''); - if (!empty($sFileHash)) - { - $oFilesProvider->Clear($oAccount, $sFileHash); - } - } - - if (!$bError) - { - $mResult = array( - 'Files' => array(array( - 'FileName' => 'attachments.zip', - 'Hash' => Utils::EncodeKeyValuesQ(array( - 'V' => APP_VERSION, - 'Account' => $oAccount ? \md5($oAccount->Hash()) : '', - 'FileName' => 'attachments.zip', - 'MimeType' => 'application/zip', - 'FileHash' => $sZipHash - )) - )) - ); - } - } - break; - } - } - else - { - $bError = true; - } - - $this->requestSleep(); - return $this->DefaultResponse(__FUNCTION__, $bError ? false : $mResult); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoIdentityUpdate() : array - { - $oAccount = $this->getAccountFromToken(); - - $oIdentity = new Model\Identity(); - if (!$oIdentity->FromJSON($this->GetActionParams(), true)) - { - throw new Exceptions\ClientException(Notifications::InvalidInputArgument); - } - - $aIdentities = $this->GetIdentities($oAccount); - - $bAdded = false; - $aIdentitiesForSave = array(); - foreach ($aIdentities as $oItem) - { - if ($oItem) - { - if ($oItem->Id() === $oIdentity->Id()) - { - $aIdentitiesForSave[] = $oIdentity; - $bAdded = true; - } - else - { - $aIdentitiesForSave[] = $oItem; - } - } - } - - if (!$bAdded) - { - $aIdentitiesForSave[] = $oIdentity; - } - - return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentitiesForSave)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoIdentityDelete() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::IDENTITIES, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sId = \trim($this->GetActionParam('IdToDelete', '')); - if (empty($sId)) - { - throw new Exceptions\ClientException(Notifications::UnknownError); - } - - $aNew = array(); - $aIdentities = $this->GetIdentities($oAccount); - - foreach ($aIdentities as $oItem) - { - if ($oItem && $sId !== $oItem->Id()) - { - $aNew[] = $oItem; - } - } - - return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aNew)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoTemplateSetup() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::TEMPLATES, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $oTemplate = new Model\Template(); - if (!$oTemplate->FromJSON($this->GetActionParams(), true)) - { - throw new Exceptions\ClientException(Notifications::InvalidInputArgument); - } - - if ('' === $oTemplate->Id()) - { - $oTemplate->GenerateID(); - } - - $aTemplatesForSave = array(); - $aTemplates = $this->GetTemplates($oAccount); - - - foreach ($aTemplates as $oItem) - { - if ($oItem && $oItem->Id() !== $oTemplate->Id()) - { - $aTemplatesForSave[] = $oItem; - } - } - - $aTemplatesForSave[] = $oTemplate; - - return $this->DefaultResponse(__FUNCTION__, $this->SetTemplates($oAccount, $aTemplatesForSave)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoTemplateDelete() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::TEMPLATES, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sId = \trim($this->GetActionParam('IdToDelete', '')); - if (empty($sId)) - { - throw new Exceptions\ClientException(Notifications::UnknownError); - } - - $aNew = array(); - $aTemplates = $this->GetTemplates($oAccount); - foreach ($aTemplates as $oItem) - { - if ($oItem && $sId !== $oItem->Id()) - { - $aNew[] = $oItem; - } - } - - return $this->DefaultResponse(__FUNCTION__, $this->SetTemplates($oAccount, $aNew)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoTemplateGetByID() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::TEMPLATES, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sId = \trim($this->GetActionParam('ID', '')); - if (empty($sId)) - { - throw new Exceptions\ClientException(Notifications::UnknownError); - } - - $oTemplate = false; - $aTemplates = $this->GetTemplates($oAccount); - - foreach ($aTemplates as $oItem) - { - if ($oItem && $sId === $oItem->Id()) - { - $oTemplate = $oItem; - break; - } - } - - $oTemplate->SetPopulateAlways(true); - return $this->DefaultResponse(__FUNCTION__, $oTemplate); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoAccountsAndIdentitiesSortOrder() : array - { - $oAccount = $this->getAccountFromToken(); - - $aAccounts = $this->GetActionParam('Accounts', null); - $aIdentities = $this->GetActionParam('Identities', null); - - if (!\is_array($aAccounts) && !\is_array($aIdentities)) - { - return $this->FalseResponse(__FUNCTION__); - } - - return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount, - Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_identities_order', - \json_encode(array( - 'Accounts' => \is_array($aAccounts) ? $aAccounts : array(), - 'Identities' => \is_array($aIdentities) ? $aIdentities : array() - )) - )); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoAccountsAndIdentities() : array - { - $oAccount = $this->getAccountFromToken(); - - $mAccounts = false; - - if ($this->GetCapa(false, false, Enumerations\Capa::ADDITIONAL_ACCOUNTS, $oAccount)) - { - $mAccounts = $this->GetAccounts($oAccount); - $mAccounts = \array_keys($mAccounts); - - foreach ($mAccounts as $iIndex => $sName) - { - $mAccounts[$iIndex] = \MailSo\Base\Utils::IdnToUtf8($sName); - } - } - - return $this->DefaultResponse(__FUNCTION__, array( - 'Accounts' => $mAccounts, - 'Identities' => $this->GetIdentities($oAccount) - )); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoTemplates() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::TEMPLATES, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - return $this->DefaultResponse(__FUNCTION__, array( - 'Templates' => $this->GetTemplates($oAccount) - )); - } - /** * @throws \MailSo\Base\Exceptions\Exception */ @@ -2751,111 +2174,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut } } - public function DoLogout() : array - { - $oAccount = $this->getAccountFromToken(false); - if ($oAccount) - { - if ($oAccount->SignMe()) - { - $this->ClearSignMeData($oAccount); - } - - if (!$oAccount->IsAdditionalAccount()) - { - Utils::ClearCookie(Actions::AUTH_SPEC_TOKEN_KEY); - } - } - - return $this->TrueResponse(__FUNCTION__); - } - - public function DoAppDelayStart() : array - { - $this->Plugins()->RunHook('service.app-delay-start-begin'); - - Utils::UpdateConnectionToken(); - - $bMainCache = false; - $bFilesCache = false; - $bVersionsCache = false; - - $iOneDay1 = 60 * 60 * 23; - $iOneDay2 = 60 * 60 * 25; - $iOneDay3 = 60 * 60 * 30; - - $sTimers = $this->StorageProvider()->Get(null, - Providers\Storage\Enumerations\StorageType::NOBODY, 'Cache/Timers', ''); - - $aTimers = \explode(',', $sTimers); - - $iMainCacheTime = !empty($aTimers[0]) && \is_numeric($aTimers[0]) ? (int) $aTimers[0] : 0; - $iFilesCacheTime = !empty($aTimers[1]) && \is_numeric($aTimers[1]) ? (int) $aTimers[1] : 0; - $iVersionsCacheTime = !empty($aTimers[2]) && \is_numeric($aTimers[2]) ? (int) $aTimers[2] : 0; - - if (0 === $iMainCacheTime || $iMainCacheTime + $iOneDay1 < \time()) - { - $bMainCache = true; - $iMainCacheTime = \time(); - } - - if (0 === $iFilesCacheTime || $iFilesCacheTime + $iOneDay2 < \time()) - { - $bFilesCache = true; - $iFilesCacheTime = \time(); - } - - if (0 === $iVersionsCacheTime || $iVersionsCacheTime + $iOneDay3 < \time()) - { - $bVersionsCache = true; - $iVersionsCacheTime = \time(); - } - - if ($bMainCache || $bFilesCache || $bVersionsCache) - { - if (!$this->StorageProvider()->Put(null, - Providers\Storage\Enumerations\StorageType::NOBODY, 'Cache/Timers', - \implode(',', array($iMainCacheTime, $iFilesCacheTime, $iVersionsCacheTime)))) - { - $bMainCache = $bFilesCache = $bVersionsCache = false; - } - } - - if ($bMainCache) - { - $this->Logger()->Write('Cacher GC: Begin'); - $this->Cacher()->GC(48); - $this->Logger()->Write('Cacher GC: End'); - } - else if ($bFilesCache) - { - $this->Logger()->Write('Files GC: Begin'); - $this->FilesProvider()->GC(48); - $this->Logger()->Write('Files GC: End'); - } - - $this->Plugins()->RunHook('service.app-delay-start-end'); - - return $this->TrueResponse(__FUNCTION__); - } - - public function DoSystemFoldersUpdate() : array - { - $oAccount = $this->getAccountFromToken(); - - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - - $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(true)->Save($oAccount, $oSettingsLocal)); - } - public function setConfigFromParams(Config\Application $oConfig, string $sParamName, string $sConfigSector, string $sConfigName, string $sType = 'string', ?callable $mStringCallback = null) : void { $sValue = $this->GetActionParam($sParamName, ''); @@ -2924,71 +2242,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut } } - public function DoSettingsUpdate() : array - { - $oAccount = $this->getAccountFromToken(); - if (!$this->GetCapa(false, false, Enumerations\Capa::SETTINGS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $self = $this; - $oConfig = $this->Config(); - - $oSettings = $this->SettingsProvider()->Load($oAccount); - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - - if ($oConfig->Get('webmail', 'allow_languages_on_settings', true)) - { - $this->setSettingsFromParams($oSettings, 'Language', 'string', function ($sLanguage) use ($self) { - return $self->ValidateLanguage($sLanguage); - }); - } - else - { - $oSettings->SetConf('Language', $this->ValidateLanguage($oConfig->Get('webmail', 'language', 'en'))); - } - - if ($this->GetCapa(false, false, Enumerations\Capa::THEMES, $oAccount)) - { - $this->setSettingsFromParams($oSettingsLocal, 'Theme', 'string', function ($sTheme) use ($self) { - return $self->ValidateTheme($sTheme); - }); - } - else - { - $oSettingsLocal->SetConf('Theme', $this->ValidateTheme($oConfig->Get('webmail', 'theme', 'Default'))); - } - - $this->setSettingsFromParams($oSettings, 'MPP', 'int', function ($iValue) { - return (int) (\in_array($iValue, array(10, 20, 30, 50, 100, 150, 200, 300)) ? $iValue : 20); - }); - - $this->setSettingsFromParams($oSettings, 'Layout', 'int', function ($iValue) { - return (int) (\in_array((int) $iValue, array(Enumerations\Layout::NO_PREVIW, - Enumerations\Layout::SIDE_PREVIEW, Enumerations\Layout::BOTTOM_PREVIEW)) ? - $iValue : Enumerations\Layout::SIDE_PREVIEW); - }); - - $this->setSettingsFromParams($oSettings, 'EditorDefaultType', 'string'); - $this->setSettingsFromParams($oSettings, 'ShowImages', 'bool'); - $this->setSettingsFromParams($oSettings, 'ContactsAutosave', 'bool'); - $this->setSettingsFromParams($oSettings, 'DesktopNotifications', 'bool'); - $this->setSettingsFromParams($oSettings, 'SoundNotification', 'bool'); - $this->setSettingsFromParams($oSettings, 'UseCheckboxesInList', 'bool'); - $this->setSettingsFromParams($oSettings, 'AllowDraftAutosave', 'bool'); - $this->setSettingsFromParams($oSettings, 'AutoLogout', 'int'); - - $this->setSettingsFromParams($oSettings, 'EnableTwoFactor', 'bool'); - - $this->setSettingsFromParams($oSettingsLocal, 'UseThreads', 'bool'); - $this->setSettingsFromParams($oSettingsLocal, 'ReplySameFolder', 'bool'); - - return $this->DefaultResponse(__FUNCTION__, - $this->SettingsProvider()->Save($oAccount, $oSettings) && - $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); - } - public function DoNoop() : array { $this->initMailClientConnection(); @@ -3164,513 +2417,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut } } - public function DoFolders() : array - { - $oAccount = $this->initMailClientConnection(); - - $oFolderCollection = null; - $this->Plugins()->RunHook('filter.folders-before', array($oAccount, $oFolderCollection)); - - $bUseFolders = $this->GetCapa(false, false, Enumerations\Capa::FOLDERS, $oAccount); - - if (null === $oFolderCollection) - { - $oFolderCollection = $this->MailClient()->Folders('', - $bUseFolders ? '*' : 'INBOX', - !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true), - (int) $this->Config()->Get('labs', 'imap_folder_list_limit', 200) - ); - } - - $this->Plugins()->RunHook('filter.folders-post', array($oAccount, $oFolderCollection)); - - if ($oFolderCollection instanceof \MailSo\Mail\FolderCollection) - { - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - - $aSystemFolders = array(); - $this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders); - $oFolderCollection->SystemFolders = $aSystemFolders; - - if ($bUseFolders && $this->Config()->Get('labs', 'autocreate_system_folders', true)) - { - $bDoItAgain = false; - - $sNamespace = $oFolderCollection->GetNamespace(); - $sParent = empty($sNamespace) ? '' : \substr($sNamespace, 0, -1); - - $sDelimiter = $oFolderCollection->FindDelimiter(); - - $aList = array(); - $aMap = $this->systemFoldersNames($oAccount); - - if ('' === $oSettingsLocal->GetConf('SentFolder', '')) - { - $aList[] = \MailSo\Imap\Enumerations\FolderType::SENT; - } - - if ('' === $oSettingsLocal->GetConf('DraftFolder', '')) - { - $aList[] = \MailSo\Imap\Enumerations\FolderType::DRAFTS; - } - - if ('' === $oSettingsLocal->GetConf('SpamFolder', '')) - { - $aList[] = \MailSo\Imap\Enumerations\FolderType::JUNK; - } - - if ('' === $oSettingsLocal->GetConf('TrashFolder', '')) - { - $aList[] = \MailSo\Imap\Enumerations\FolderType::TRASH; - } - - if ('' === $oSettingsLocal->GetConf('ArchiveFolder', '')) - { - $aList[] = \MailSo\Imap\Enumerations\FolderType::ALL; - } - - $this->Plugins()->RunHook('filter.folders-system-types', array($oAccount, &$aList)); - - foreach ($aList as $iType) - { - if (!isset($aSystemFolders[$iType])) - { - $mFolderNameToCreate = \array_search($iType, $aMap); - if (!empty($mFolderNameToCreate)) - { - $iPos = \strrpos($mFolderNameToCreate, $sDelimiter); - if (false !== $iPos) - { - $mNewParent = \substr($mFolderNameToCreate, 0, $iPos); - $mNewFolderNameToCreate = \substr($mFolderNameToCreate, $iPos + 1); - if (0 < \strlen($mNewFolderNameToCreate)) - { - $mFolderNameToCreate = $mNewFolderNameToCreate; - } - - if (0 < \strlen($mNewParent)) - { - $sParent = 0 < \strlen($sParent) ? $sParent.$sDelimiter.$mNewParent : $mNewParent; - } - } - - $sFullNameToCheck = \MailSo\Base\Utils::ConvertEncoding($mFolderNameToCreate, - \MailSo\Base\Enumerations\Charset::UTF_8, \MailSo\Base\Enumerations\Charset::UTF_7_IMAP); - - if (0 < \strlen(\trim($sParent))) - { - $sFullNameToCheck = $sParent.$sDelimiter.$sFullNameToCheck; - } - - if (!$oFolderCollection->GetByFullNameRaw($sFullNameToCheck)) - { - try - { - if ($this->MailClient()->FolderCreate($mFolderNameToCreate, $sParent, true, $sDelimiter)) - { - $bDoItAgain = true; - } - } - catch (\Throwable $oException) - { - $this->Logger()->WriteException($oException); - } - } - } - } - } - - if ($bDoItAgain) - { - $oFolderCollection = $this->MailClient()->Folders('', '*', - !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true), - (int) $this->Config()->Get('labs', 'imap_folder_list_limit', 200) - ); - - if ($oFolderCollection) - { - $aSystemFolders = array(); - $this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders); - $oFolderCollection->SystemFolders = $aSystemFolders; - } - } - } - - if ($oFolderCollection) - { - $oFolderCollection->FoldersHash = \md5(\implode("\x0", $this->recFoldersNames($oFolderCollection))); - } - } - - $this->Plugins()->RunHook('filter.folders-complete', array($oAccount, $oFolderCollection)); - - return $this->DefaultResponse(__FUNCTION__, $oFolderCollection); - } - - public function DoFolderCreate() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::FOLDERS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - try - { - $sFolderNameInUtf = $this->GetActionParam('Folder', ''); - $sFolderParentFullNameRaw = $this->GetActionParam('Parent', ''); - - $this->MailClient()->FolderCreate($sFolderNameInUtf, $sFolderParentFullNameRaw, - !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true)); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantCreateFolder, $oException); - } - - return $this->TrueResponse(__FUNCTION__); - } - - public function DoFolderSubscribe() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::FOLDERS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); - $bSubscribe = '1' === (string) $this->GetActionParam('Subscribe', '0'); - - try - { - $this->MailClient()->FolderSubscribe($sFolderFullNameRaw, !!$bSubscribe); - } - catch (\Throwable $oException) - { - if ($bSubscribe) - { - throw new Exceptions\ClientException(Notifications::CantSubscribeFolder, $oException); - } - else - { - throw new Exceptions\ClientException(Notifications::CantUnsubscribeFolder, $oException); - } - } - - return $this->TrueResponse(__FUNCTION__); - } - - public function DoFolderCheckable() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::FOLDERS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); - $bCheckable = '1' === (string) $this->GetActionParam('Checkable', '0'); - - $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); - - $sCheckableFolder = $oSettingsLocal->GetConf('CheckableFolder', '[]'); - $aCheckableFolder = \json_decode($sCheckableFolder); - - if (!\is_array($aCheckableFolder)) - { - $aCheckableFolder = array(); - } - - if ($bCheckable) - { - $aCheckableFolder[] = $sFolderFullNameRaw; - } - else - { - $aCheckableFolderNew = array(); - foreach ($aCheckableFolder as $sFolder) - { - if ($sFolder !== $sFolderFullNameRaw) - { - $aCheckableFolderNew[] = $sFolder; - } - } - $aCheckableFolder = $aCheckableFolderNew; - } - - $aCheckableFolder = \array_unique($aCheckableFolder); - - $oSettingsLocal->SetConf('CheckableFolder', \json_encode($aCheckableFolder)); - - return $this->DefaultResponse(__FUNCTION__, - $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoFolderRename() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::FOLDERS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sPrevFolderFullNameRaw = $this->GetActionParam('Folder', ''); - $sNewTopFolderNameInUtf = $this->GetActionParam('NewFolderName', ''); - - try - { - $this->MailClient()->FolderRename($sPrevFolderFullNameRaw, $sNewTopFolderNameInUtf, - !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true)); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantRenameFolder, $oException); - } - - return $this->TrueResponse(__FUNCTION__); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoFolderDelete() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::FOLDERS, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); - - try - { - $this->MailClient()->FolderDelete($sFolderFullNameRaw, - !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true)); - } - catch (\MailSo\Mail\Exceptions\NonEmptyFolder $oException) - { - throw new Exceptions\ClientException(Notifications::CantDeleteNonEmptyFolder, $oException); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantDeleteFolder, $oException); - } - - return $this->TrueResponse(__FUNCTION__); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoFolderClear() : array - { - $this->initMailClientConnection(); - - $sFolderFullNameRaw = $this->GetActionParam('Folder', ''); - - try - { - $this->MailClient()->FolderClear($sFolderFullNameRaw); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::MailServerError, $oException); - } - - return $this->TrueResponse(__FUNCTION__); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoFolderInformation() : array - { - $sFolder = $this->GetActionParam('Folder', ''); - $sPrevUidNext = $this->GetActionParam('UidNext', ''); - $aFlagsUids = array(); - $sFlagsUids = (string) $this->GetActionParam('FlagsUids', ''); - - $aFlagsFilteredUids = array(); - if (0 < strlen($sFlagsUids)) - { - $aFlagsUids = explode(',', $sFlagsUids); - $aFlagsFilteredUids = array_filter($aFlagsUids, function (&$sUid) { - $sUid = (int) trim($sUid); - return 0 < (int) trim($sUid); - }); - } - - $this->initMailClientConnection(); - - $sForwardedFlag = $this->Config()->Get('labs', 'imap_forwarded_flag', ''); - $sReadReceiptFlag = $this->Config()->Get('labs', 'imap_read_receipt_flag', ''); - try - { - $aInboxInformation = $this->MailClient()->FolderInformation( - $sFolder, $sPrevUidNext, $aFlagsFilteredUids - ); - - if (isset($aInboxInformation['Flags']) && \is_array($aInboxInformation['Flags'])) - { - foreach ($aInboxInformation['Flags'] as $iUid => $aFlags) - { - $aLowerFlags = array_map('strtolower', $aFlags); - $aInboxInformation['Flags'][$iUid] = array( - 'IsSeen' => in_array('\\seen', $aLowerFlags), - 'IsFlagged' => in_array('\\flagged', $aLowerFlags), - 'IsAnswered' => in_array('\\answered', $aLowerFlags), - 'IsDeleted' => in_array('\\deleted', $aLowerFlags), - 'IsForwarded' => 0 < strlen($sForwardedFlag) && in_array(strtolower($sForwardedFlag), $aLowerFlags), - 'IsReadReceipt' => 0 < strlen($sReadReceiptFlag) && in_array(strtolower($sReadReceiptFlag), $aLowerFlags) - ); - } - } - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::MailServerError, $oException); - } - - $aInboxInformation['Version'] = APP_VERSION; - - return $this->DefaultResponse(__FUNCTION__, $aInboxInformation); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoFolderInformationMultiply() : array - { - $aResult = array( - 'List' => array(), - 'Version' => APP_VERSION - ); - - $aFolders = $this->GetActionParam('Folders', null); - if (\is_array($aFolders)) - { - $this->initMailClientConnection(); - - $aFolders = \array_unique($aFolders); - foreach ($aFolders as $sFolder) - { - if (0 < \strlen(\trim($sFolder)) && 'INBOX' !== \strtoupper($sFolder)) - { - try - { - $aInboxInformation = $this->MailClient()->FolderInformation($sFolder, '', array()); - if (isset($aInboxInformation['Folder'])) - { - $aResult['List'][] = $aInboxInformation; - } - } - catch (\Throwable $oException) - { - $this->Logger()->WriteException($oException); - } - } - } - } - - return $this->DefaultResponse(__FUNCTION__, $aResult); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessageList() : array - { -// \sleep(1); -// throw new Exceptions\ClientException(Notifications::CantGetMessageList); - - $sFolder = ''; - $iOffset = 0; - $iLimit = 20; - $sSearch = ''; - $sUidNext = ''; - $bUseThreads = false; - $sThreadUid = ''; - - $sRawKey = $this->GetActionParam('RawKey', ''); - $aValues = $this->getDecodedClientRawKeyValue($sRawKey, 9); - - if ($aValues && 7 < \count($aValues)) - { - $sFolder =(string) $aValues[0]; - $iOffset = (int) $aValues[1]; - $iLimit = (int) $aValues[2]; - $sSearch = (string) $aValues[3]; - $sUidNext = (string) $aValues[6]; - $bUseThreads = (bool) $aValues[7]; - - if ($bUseThreads) - { - $sThreadUid = isset($aValues[8]) ? (string) $aValues[8] : ''; - } - - $this->verifyCacheByKey($sRawKey); - } - else - { - $sFolder = $this->GetActionParam('Folder', ''); - $iOffset = (int) $this->GetActionParam('Offset', 0); - $iLimit = (int) $this->GetActionParam('Limit', 10); - $sSearch = $this->GetActionParam('Search', ''); - $sUidNext = $this->GetActionParam('UidNext', ''); - $bUseThreads = '1' === (string) $this->GetActionParam('UseThreads', '0'); - - if ($bUseThreads) - { - $sThreadUid = (string) $this->GetActionParam('ThreadUid', ''); - } - } - - if (0 === strlen($sFolder)) - { - throw new Exceptions\ClientException(Notifications::CantGetMessageList); - } - - $this->initMailClientConnection(); - - try - { - if (!$this->Config()->Get('labs', 'use_imap_thread', false)) - { - $bUseThreads = false; - } - - $oMessageList = $this->MailClient()->MessageList( - $sFolder, $iOffset, $iLimit, $sSearch, $sUidNext, - $this->cacherForUids(), - !!$this->Config()->Get('labs', 'use_imap_sort', false), - $bUseThreads, - $sThreadUid, - '' - ); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantGetMessageList, $oException); - } - - if ($oMessageList) - { - $this->cacheByKey($sRawKey); - } - - return $this->DefaultResponse(__FUNCTION__, $oMessageList); - } - private function buildMessage(Model\Account $oAccount, bool $bWithDraftInfo = true) : \MailSo\Mime\Message { $sIdentityID = $this->GetActionParam('IdentityID', ''); @@ -3910,73 +2656,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return $oMessage; } - public function DoSaveMessage() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::COMPOSER, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sMessageFolder = $this->GetActionParam('MessageFolder', ''); - $sMessageUid = $this->GetActionParam('MessageUid', ''); - - $sDraftFolder = $this->GetActionParam('SaveFolder', ''); - if (0 === strlen($sDraftFolder)) - { - throw new Exceptions\ClientException(Notifications::UnknownError); - } - - $oMessage = $this->buildMessage($oAccount, true); - - $this->Plugins()->RunHook('filter.save-message', array($oMessage)); - - $mResult = false; - if ($oMessage) - { - $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); - - $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( - $oMessage->ToStream(false), array($rMessageStream), 8192, true, true); - - if (false !== $iMessageStreamSize) - { - $sMessageId = $oMessage->MessageId(); - - \rewind($rMessageStream); - - $iNewUid = 0; - $this->MailClient()->MessageAppendStream( - $rMessageStream, $iMessageStreamSize, $sDraftFolder, array( - \MailSo\Imap\Enumerations\MessageFlag::SEEN - ), $iNewUid); - - if (!empty($sMessageId) && (null === $iNewUid || 0 === $iNewUid)) - { - $iNewUid = $this->MailClient()->FindMessageUidByMessageId($sDraftFolder, $sMessageId); - } - - $mResult = true; - - if (0 < strlen($sMessageFolder) && 0 < strlen($sMessageUid)) - { - $this->MailClient()->MessageDelete($sMessageFolder, array($sMessageUid), true, true); - } - - if (null !== $iNewUid && 0 < $iNewUid) - { - $mResult = array( - 'NewFolder' => $sDraftFolder, - 'NewUid' => $iNewUid - ); - } - } - } - - return $this->DefaultResponse(__FUNCTION__, $mResult); - } - /** * @throws \RainLoop\Exceptions\ClientException * @throws \MailSo\Net\Exceptions\ConnectionException @@ -4132,281 +2811,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut } } - public function DoSendMessage() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::COMPOSER, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $oConfig = $this->Config(); - - $sDraftFolder = $this->GetActionParam('MessageFolder', ''); - $sDraftUid = $this->GetActionParam('MessageUid', ''); - $sSentFolder = $this->GetActionParam('SaveFolder', ''); - $aDraftInfo = $this->GetActionParam('DraftInfo', null); - $bDsn = '1' === (string) $this->GetActionParam('Dsn', '0'); - - $oMessage = $this->buildMessage($oAccount, false); - - $this->Plugins()->RunHook('filter.send-message', array($oMessage)); - - $mResult = false; - try - { - if ($oMessage) - { - $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); - - $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( - $oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true); - - if (false !== $iMessageStreamSize) - { - $this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, $bDsn, true); - - if (\is_array($aDraftInfo) && 3 === \count($aDraftInfo)) - { - $sDraftInfoType = $aDraftInfo[0]; - $sDraftInfoUid = $aDraftInfo[1]; - $sDraftInfoFolder = $aDraftInfo[2]; - - try - { - switch (\strtolower($sDraftInfoType)) - { - case 'reply': - case 'reply-all': - $this->MailClient()->MessageSetFlag($sDraftInfoFolder, array($sDraftInfoUid), true, - \MailSo\Imap\Enumerations\MessageFlag::ANSWERED, true); - break; - case 'forward': - $sForwardedFlag = $this->Config()->Get('labs', 'imap_forwarded_flag', ''); - if (0 < strlen($sForwardedFlag)) - { - $this->MailClient()->MessageSetFlag($sDraftInfoFolder, array($sDraftInfoUid), true, - $sForwardedFlag, true); - } - break; - } - } - catch (\Throwable $oException) - { - $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); - } - } - - if (0 < \strlen($sSentFolder)) - { - try - { - if (!$oMessage->GetBcc()) - { - if (\is_resource($rMessageStream)) - { - \rewind($rMessageStream); - } - - $this->Plugins()->RunHook('filter.send-message-stream', - array($oAccount, &$rMessageStream, &$iMessageStreamSize)); - - $this->MailClient()->MessageAppendStream( - $rMessageStream, $iMessageStreamSize, $sSentFolder, array( - \MailSo\Imap\Enumerations\MessageFlag::SEEN - ) - ); - } - else - { - $rAppendMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); - - $iAppendMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( - $oMessage->ToStream(false), array($rAppendMessageStream), 8192, true, true, true); - - $this->Plugins()->RunHook('filter.send-message-stream', - array($oAccount, &$rAppendMessageStream, &$iAppendMessageStreamSize)); - - $this->MailClient()->MessageAppendStream( - $rAppendMessageStream, $iAppendMessageStreamSize, $sSentFolder, array( - \MailSo\Imap\Enumerations\MessageFlag::SEEN - )); - - if (\is_resource($rAppendMessageStream)) - { - fclose($rAppendMessageStream); - } - } - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantSaveMessage, $oException); - } - } - - if (\is_resource($rMessageStream)) - { - \fclose($rMessageStream); - } - - $this->deleteMessageAttachmnets($oAccount); - - if (0 < \strlen($sDraftFolder) && 0 < \strlen($sDraftUid)) - { - try - { - $this->MailClient()->MessageDelete($sDraftFolder, array($sDraftUid), true, true); - } - catch (\Throwable $oException) - { - $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); - } - } - - $mResult = true; - } - } - } - catch (Exceptions\ClientException $oException) - { - throw $oException; - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantSendMessage, $oException); - } - - if (false === $mResult) - { - throw new Exceptions\ClientException(Notifications::CantSendMessage); - } - - try - { - if ($oMessage && $this->AddressBookProvider($oAccount)->IsActive()) - { - $aArrayToFrec = array(); - $oToCollection = $oMessage->GetTo(); - if ($oToCollection) - { - foreach ($oToCollection as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) - { - $aArrayToFrec[$oEmail->GetEmail(true)] = $oEmail->ToString(false, true); - } - } - - if (0 < \count($aArrayToFrec)) - { - $oSettings = $this->SettingsProvider()->Load($oAccount); - - $this->AddressBookProvider($oAccount)->IncFrec( - $oAccount->ParentEmailHelper(), \array_values($aArrayToFrec), - !!$oSettings->GetConf('ContactsAutosave', - !!$oConfig->Get('defaults', 'contacts_autosave', true))); - } - } - } - catch (\Throwable $oException) - { - $this->Logger()->WriteException($oException); - } - - return $this->TrueResponse(__FUNCTION__); - } - - public function DoSendReadReceiptMessage() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::COMPOSER, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $oMessage = $this->buildReadReceiptMessage($oAccount); - - $this->Plugins()->RunHook('filter.send-read-receipt-message', array($oMessage, $oAccount)); - - $mResult = false; - try - { - if ($oMessage) - { - $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); - - $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( - $oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true); - - if (false !== $iMessageStreamSize) - { - $this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, false, false); - - if (\is_resource($rMessageStream)) - { - \fclose($rMessageStream); - } - - $mResult = true; - - $sReadReceiptFlag = $this->Config()->Get('labs', 'imap_read_receipt_flag', ''); - if (!empty($sReadReceiptFlag)) - { - $sFolderFullName = $this->GetActionParam('MessageFolder', ''); - $sUid = $this->GetActionParam('MessageUid', ''); - - $this->Cacher($oAccount)->Set(KeyPathHelper::ReadReceiptCache($oAccount->Email(), $sFolderFullName, $sUid), '1'); - - if (0 < \strlen($sFolderFullName) && 0 < \strlen($sUid)) - { - try - { - $this->MailClient()->MessageSetFlag($sFolderFullName, array($sUid), true, $sReadReceiptFlag, true, true); - } - catch (\Throwable $oException) {} - } - } - } - } - } - catch (Exceptions\ClientException $oException) - { - throw $oException; - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantSendMessage, $oException); - } - - if (false === $mResult) - { - throw new Exceptions\ClientException(Notifications::CantSendMessage); - } - - return $this->TrueResponse(__FUNCTION__); - } - - public function DoQuota() : array - { - $oAccount = $this->initMailClientConnection(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::QUOTA, $oAccount)) - { - return $this->DefaultResponse(__FUNCTION__, array(0, 0, 0, 0)); - } - - try - { - $aQuota = $this->MailClient()->Quota(); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::MailServerError, $oException); - } - - return $this->DefaultResponse(__FUNCTION__, $aQuota); - } - private function getContactsSyncData(Model\Account $oAccount) : ?array { $mResult = null; @@ -4433,63 +2837,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return $mResult; } - public function DoSaveContactsSyncData() : array - { - $oAccount = $this->getAccountFromToken(); - - $oAddressBookProvider = $this->AddressBookProvider($oAccount); - if (!$oAddressBookProvider || !$oAddressBookProvider->IsActive()) - { - return $this->FalseResponse(__FUNCTION__); - } - - $bEnabled = '1' === (string) $this->GetActionParam('Enable', '0'); - $sUrl = $this->GetActionParam('Url', ''); - $sUser = $this->GetActionParam('User', ''); - $sPassword = $this->GetActionParam('Password', ''); - - $mData = $this->getContactsSyncData($oAccount); - - $bResult = $this->StorageProvider()->Put($oAccount, - Providers\Storage\Enumerations\StorageType::CONFIG, - 'contacts_sync', - Utils::EncodeKeyValues(array( - 'Enable' => $bEnabled, - 'User' => $sUser, - 'Password' => APP_DUMMY === $sPassword && isset($mData['Password']) ? - $mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword), - 'Url' => $sUrl - )) - ); - - return $this->DefaultResponse(__FUNCTION__, $bResult); - } - - public function DoContactsSync() : array - { - $bResult = false; - $oAccount = $this->getAccountFromToken(); - - $oAddressBookProvider = $this->AddressBookProvider($oAccount); - if ($oAddressBookProvider && $oAddressBookProvider->IsActive()) - { - $mData = $this->getContactsSyncData($oAccount); - if (isset($mData['Enable'], $mData['User'], $mData['Password'], $mData['Url']) && $mData['Enable']) - { - $bResult = $oAddressBookProvider->Sync( - $oAccount->ParentEmailHelper(), - $mData['Url'], $mData['User'], $mData['Password']); - } - } - - if (!$bResult) - { - throw new Exceptions\ClientException(Notifications::ContactsSyncError); - } - - return $this->TrueResponse(__FUNCTION__); - } - private function getTwoFactorInfo(Model\Account $oAccount, bool $bRemoveSecret = false) : array { $sEmail = $oAccount->ParentEmailHelper(); @@ -4586,335 +2933,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return false; } - public function DoGetTwoFactorInfo() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->TwoFactorAuthProvider()->IsActive() || - !$this->GetCapa(false, false, Enumerations\Capa::TWO_FACTOR, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - return $this->DefaultResponse(__FUNCTION__, - $this->getTwoFactorInfo($oAccount, true)); - } - - public function DoCreateTwoFactorSecret() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->TwoFactorAuthProvider()->IsActive() || - !$this->GetCapa(false, false, Enumerations\Capa::TWO_FACTOR, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sEmail = $oAccount->ParentEmailHelper(); - - $sSecret = $this->TwoFactorAuthProvider()->CreateSecret(); - - $aCodes = array(); - for ($iIndex = 9; $iIndex > 0; $iIndex--) - { - $aCodes[] = \rand(100000000, 900000000); - } - - $this->StorageProvider()->Put($oAccount, - Providers\Storage\Enumerations\StorageType::CONFIG, - 'two_factor', - Utils::EncodeKeyValues(array( - 'User' => $sEmail, - 'Enable' => false, - 'Secret' => $sSecret, - 'BackupCodes' => \implode(' ', $aCodes) - )) - ); - - $this->requestSleep(); - - return $this->DefaultResponse(__FUNCTION__, - $this->getTwoFactorInfo($oAccount)); - } - - public function DoShowTwoFactorSecret() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->TwoFactorAuthProvider()->IsActive() || - !$this->GetCapa(false, false, Enumerations\Capa::TWO_FACTOR, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $aResult = $this->getTwoFactorInfo($oAccount); - unset($aResult['BackupCodes']); - - return $this->DefaultResponse(__FUNCTION__, $aResult); - } - - public function DoEnableTwoFactor() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->TwoFactorAuthProvider()->IsActive() || - !$this->GetCapa(false, false, Enumerations\Capa::TWO_FACTOR, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sEmail = $oAccount->ParentEmailHelper(); - - $bResult = false; - $mData = $this->getTwoFactorInfo($oAccount); - if (isset($mData['Secret'], $mData['BackupCodes'])) - { - $bResult = $this->StorageProvider()->Put($oAccount, - Providers\Storage\Enumerations\StorageType::CONFIG, - 'two_factor', - Utils::EncodeKeyValues(array( - 'User' => $sEmail, - 'Enable' => '1' === \trim($this->GetActionParam('Enable', '0')), - 'Secret' => $mData['Secret'], - 'BackupCodes' => $mData['BackupCodes'] - )) - ); - } - - return $this->DefaultResponse(__FUNCTION__, $bResult); - } - - public function DoTestTwoFactorInfo() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->TwoFactorAuthProvider()->IsActive() || - !$this->GetCapa(false, false, Enumerations\Capa::TWO_FACTOR, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $sCode = \trim($this->GetActionParam('Code', '')); - - $aData = $this->getTwoFactorInfo($oAccount); - $sSecret = !empty($aData['Secret']) ? $aData['Secret'] : ''; - -// $this->Logger()->WriteDump(array( -// $sCode, $sSecret, $aData, -// $this->TwoFactorAuthProvider()->VerifyCode($sSecret, $sCode) -// )); - - $this->requestSleep(); - - return $this->DefaultResponse(__FUNCTION__, - $this->TwoFactorAuthProvider()->VerifyCode($sSecret, $sCode)); - } - - public function DoClearTwoFactorInfo() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->TwoFactorAuthProvider()->IsActive() || - !$this->GetCapa(false, false, Enumerations\Capa::TWO_FACTOR, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $this->StorageProvider()->Clear($oAccount, - Providers\Storage\Enumerations\StorageType::CONFIG, - 'two_factor' - ); - - return $this->DefaultResponse(__FUNCTION__, - $this->getTwoFactorInfo($oAccount, true)); - } - - public function DoContacts() : array - { - $oAccount = $this->getAccountFromToken(); - - $sSearch = \trim($this->GetActionParam('Search', '')); - $iOffset = (int) $this->GetActionParam('Offset', 0); - $iLimit = (int) $this->GetActionParam('Limit', 20); - $iOffset = 0 > $iOffset ? 0 : $iOffset; - $iLimit = 0 > $iLimit ? 20 : $iLimit; - - $iResultCount = 0; - $mResult = array(); - - $oAbp = $this->AddressBookProvider($oAccount); - if ($oAbp->IsActive()) - { - $iResultCount = 0; - $mResult = $oAbp->GetContacts($oAccount->ParentEmailHelper(), - $iOffset, $iLimit, $sSearch, $iResultCount); - } - - return $this->DefaultResponse(__FUNCTION__, array( - 'Offset' => $iOffset, - 'Limit' => $iLimit, - 'Count' => $iResultCount, - 'Search' => $sSearch, - 'List' => $mResult - )); - } - - public function DoContactsDelete() : array - { - $oAccount = $this->getAccountFromToken(); - $aUids = \explode(',', (string) $this->GetActionParam('Uids', '')); - - $aFilteredUids = \array_filter($aUids, function (&$mUid) { - $mUid = (int) \trim($mUid); - return 0 < $mUid; - }); - - $bResult = false; - if (0 < \count($aFilteredUids) && $this->AddressBookProvider($oAccount)->IsActive()) - { - $bResult = $this->AddressBookProvider($oAccount)->DeleteContacts($oAccount->ParentEmailHelper(), $aFilteredUids); - } - - return $this->DefaultResponse(__FUNCTION__, $bResult); - } - - public function DoContactSave() : array - { - $oAccount = $this->getAccountFromToken(); - - $bResult = false; - - $oAddressBookProvider = $this->AddressBookProvider($oAccount); - $sRequestUid = \trim($this->GetActionParam('RequestUid', '')); - if ($oAddressBookProvider && $oAddressBookProvider->IsActive() && 0 < \strlen($sRequestUid)) - { - $sUid = \trim($this->GetActionParam('Uid', '')); - - $oContact = null; - if (0 < \strlen($sUid)) - { - $oContact = $oAddressBookProvider->GetContactByID($oAccount->ParentEmailHelper(), $sUid); - } - - if (!$oContact) - { - $oContact = new Providers\AddressBook\Classes\Contact(); - if (0 < \strlen($sUid)) - { - $oContact->IdContact = $sUid; - } - } - - $oContact->Properties = array(); - $aProperties = $this->GetActionParam('Properties', array()); - if (\is_array($aProperties)) - { - foreach ($aProperties as $aItem) - { - if ($aItem && isset($aItem[0], $aItem[1]) && \is_numeric($aItem[0])) - { - $oProp = new Providers\AddressBook\Classes\Property(); - $oProp->Type = (int) $aItem[0]; - $oProp->Value = $aItem[1]; - $oProp->TypeStr = empty($aItem[2]) ? '': $aItem[2]; - - $oContact->Properties[] = $oProp; - } - } - } - - if (!empty($oContact->Etag)) - { - $oContact->Etag = \md5($oContact->ToVCard()); - } - - $oContact->PopulateDisplayAndFullNameValue(true); - - $bResult = $oAddressBookProvider->ContactSave($oAccount->ParentEmailHelper(), $oContact); - } - - return $this->DefaultResponse(__FUNCTION__, array( - 'RequestUid' => $sRequestUid, - 'ResultID' => $bResult ? $oContact->IdContact : '', - 'Result' => $bResult - )); - } - - public function DoSuggestions() : array - { - $oAccount = $this->getAccountFromToken(); - - $sQuery = \trim($this->GetActionParam('Query', '')); - $iLimit = (int) $this->Config()->Get('contacts', 'suggestions_limit', 20); - - $aResult = array(); - - $this->Plugins()->RunHook('ajax.suggestions-input-parameters', array(&$sQuery, &$iLimit, $oAccount)); - - $iLimit = (int) $iLimit; - if (5 > $iLimit) - { - $iLimit = 5; - } - - $this->Plugins()->RunHook('ajax.suggestions-pre', array(&$aResult, $sQuery, $oAccount, $iLimit)); - - if ($iLimit > \count($aResult) && 0 < \strlen($sQuery)) - { - try - { - // Address Book - $oAddressBookProvider = $this->AddressBookProvider($oAccount); - if ($oAddressBookProvider && $oAddressBookProvider->IsActive()) - { - $aSuggestions = $oAddressBookProvider->GetSuggestions($oAccount->ParentEmailHelper(), $sQuery, $iLimit); - if (0 === \count($aResult)) - { - $aResult = $aSuggestions; - } - else - { - $aResult = \array_merge($aResult, $aSuggestions); - } - } - } - catch (\Throwable $oException) - { - $this->Logger()->WriteException($oException); - } - } - - if ($iLimit > \count($aResult) && 0 < \strlen($sQuery)) - { - $oSuggestionsProvider = $this->SuggestionsProvider(); - if ($oSuggestionsProvider && $oSuggestionsProvider->IsActive()) - { - $aSuggestionsProviderResult = $oSuggestionsProvider->Process($oAccount, $sQuery, $iLimit); - if (\is_array($aSuggestionsProviderResult) && 0 < \count($aSuggestionsProviderResult)) - { - $aResult = \array_merge($aResult, $aSuggestionsProviderResult); - } - } - - } - - $aResult = Utils::RemoveSuggestionDuplicates($aResult); - if ($iLimit < \count($aResult)) - { - $aResult = \array_slice($aResult, 0, $iLimit); - } - - $this->Plugins()->RunHook('ajax.suggestions-post', array(&$aResult, $sQuery, $oAccount, $iLimit)); - - $aResult = Utils::RemoveSuggestionDuplicates($aResult); - if ($iLimit < \count($aResult)) - { - $aResult = \array_slice($aResult, 0, $iLimit); - } - - return $this->DefaultResponse(__FUNCTION__, $aResult); - } - private function messageSetFlag(string $sActionFunction, string $sResponseFunction) : array { $this->initMailClientConnection(); @@ -4939,235 +2957,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return $this->TrueResponse($sResponseFunction); } - public function DoMessageSetSeen() : array - { - return $this->messageSetFlag('MessageSetSeen', __FUNCTION__); - } - - public function DoMessageSetSeenToAll() : array - { - $this->initMailClientConnection(); - - $sFolder = $this->GetActionParam('Folder', ''); - $bSetAction = '1' === (string) $this->GetActionParam('SetAction', '0'); - $sThreadUids = \trim($this->GetActionParam('ThreadUids', '')); - - try - { - $this->MailClient()->MessageSetSeenToAll($sFolder, $bSetAction, - !empty($sThreadUids) ? explode(',', $sThreadUids) : null); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::MailServerError, $oException); - } - - return $this->TrueResponse(__FUNCTION__); - } - - public function DoMessageSetFlagged() : array - { - return $this->messageSetFlag('MessageSetFlagged', __FUNCTION__); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessage() : array - { - $sRawKey = (string) $this->GetActionParam('RawKey', ''); - - $sFolder = ''; - $iUid = 0; - - $aValues = $this->getDecodedClientRawKeyValue($sRawKey, 4); - if ($aValues && 4 === count($aValues)) - { - $sFolder = (string) $aValues[0]; - $iUid = (int) $aValues[1]; - - $this->verifyCacheByKey($sRawKey); - } - else - { - $sFolder = $this->GetActionParam('Folder', ''); - $iUid = (int) $this->GetActionParam('Uid', 0); - } - - $oAccount = $this->initMailClientConnection(); - - try - { - $oMessage = $this->MailClient()->Message($sFolder, $iUid, true, - $this->cacherForThreads(), - (int) $this->Config()->Get('labs', 'imap_body_text_limit', 0) - ); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantGetMessage, $oException); - } - - if ($oMessage) - { - $this->Plugins()->RunHook('filter.result-message', array($oMessage)); - - $this->cacheByKey($sRawKey); - } - - return $this->DefaultResponse(__FUNCTION__, $oMessage); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessageDelete() : array - { - $this->initMailClientConnection(); - - $sFolder = $this->GetActionParam('Folder', ''); - $aUids = \explode(',', (string) $this->GetActionParam('Uids', '')); - - $aFilteredUids = \array_filter($aUids, function (&$sUid) { - $sUid = (int) \trim($sUid); - return 0 < $sUid; - }); - - try - { - $this->MailClient()->MessageDelete($sFolder, $aFilteredUids, true, true, - !!$this->Config()->Get('labs', 'use_imap_expunge_all_on_delete', false)); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantDeleteMessage, $oException); - } - - if ($this->Config()->Get('labs', 'use_imap_unselect', true)) - { - try - { - $this->MailClient()->FolderUnSelect(); - } - catch (\Throwable $oException) - { - unset($oException); - } - } - - $sHash = ''; - - try - { - $sHash = $this->MailClient()->FolderHash($sFolder); - } - catch (\Throwable $oException) - { - unset($oException); - } - - return $this->DefaultResponse(__FUNCTION__, '' === $sHash ? false : array($sFolder, $sHash)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessageMove() : array - { - $this->initMailClientConnection(); - - $sFromFolder = $this->GetActionParam('FromFolder', ''); - $sToFolder = $this->GetActionParam('ToFolder', ''); - $aUids = \explode(',', (string) $this->GetActionParam('Uids', '')); - $bMarkAsRead = '1' === (string) $this->GetActionParam('MarkAsRead', '0'); - - $aFilteredUids = \array_filter($aUids, function (&$mUid) { - $mUid = (int) \trim($mUid); - return 0 < $mUid; - }); - - if ($bMarkAsRead) - { - try - { - $this->MailClient()->MessageSetSeen($sFromFolder, $aFilteredUids, true, true); - } - catch (\Throwable $oException) - { - unset($oException); - } - } - - try - { - $this->MailClient()->MessageMove($sFromFolder, $sToFolder, $aFilteredUids, true, - !!$this->Config()->Get('labs', 'use_imap_move', true), - !!$this->Config()->Get('labs', 'use_imap_expunge_all_on_delete', false) - ); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantMoveMessage, $oException); - } - - if ($this->Config()->Get('labs', 'use_imap_unselect', true)) - { - try - { - $this->MailClient()->FolderUnSelect(); - } - catch (\Throwable $oException) - { - unset($oException); - } - } - - $sHash = ''; - - try - { - $sHash = $this->MailClient()->FolderHash($sFromFolder); - } - catch (\Throwable $oException) - { - unset($oException); - } - - return $this->DefaultResponse(__FUNCTION__, '' === $sHash ? false : array($sFromFolder, $sHash)); - } - - /** - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessageCopy() : array - { - $this->initMailClientConnection(); - - $sFromFolder = $this->GetActionParam('FromFolder', ''); - $sToFolder = $this->GetActionParam('ToFolder', ''); - $aUids = \explode(',', (string) $this->GetActionParam('Uids', '')); - - $aFilteredUids = \array_filter($aUids, function (&$mUid) { - $mUid = (int) \trim($mUid); - return 0 < $mUid; - }); - - try - { - $this->MailClient()->MessageCopy($sFromFolder, $sToFolder, - $aFilteredUids, true); - - $sHash = $this->MailClient()->FolderHash($sFromFolder); - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::CantCopyMessage, $oException); - } - - return $this->DefaultResponse(__FUNCTION__, - '' === $sHash ? false : array($sFromFolder, $sHash)); - } - public function MainClearFileName(string $sFileName, string $sContentType, string $sMimeIndex, int $iMaxLength = 250) : string { $sFileName = 0 === \strlen($sFileName) ? \preg_replace('/[^a-zA-Z0-9]/', '.', (empty($sMimeIndex) ? '' : $sMimeIndex.'.').$sContentType) : $sFileName; @@ -5182,97 +2971,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return \MailSo\Base\Utils::ClearFileName(\MailSo\Base\Utils::Utf8Clear($sClearedFileName)); } - public function DoMessageUploadAttachments() : array - { - $oAccount = $this->initMailClientConnection(); - - $mResult = false; - $self = $this; - - try - { - $aAttachments = $this->GetActionParam('Attachments', array()); - if (\is_array($aAttachments) && 0 < \count($aAttachments)) - { - $mResult = array(); - foreach ($aAttachments as $sAttachment) - { - if ($aValues = Utils::DecodeKeyValuesQ($sAttachment)) - { - $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : ''; - $iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0; - $sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : ''; - - $sTempName = \md5($sAttachment); - if (!$this->FilesProvider()->FileExists($oAccount, $sTempName)) - { - $this->MailClient()->MessageMimeStream( - function($rResource, $sContentType, $sFileName, $sMimeIndex = '') use ($oAccount, &$mResult, $sTempName, $sAttachment, $self) { - if (is_resource($rResource)) - { - $sContentType = (empty($sFileName)) ? 'text/plain' : \MailSo\Base\Utils::MimeContentType($sFileName); - $sFileName = $self->MainClearFileName($sFileName, $sContentType, $sMimeIndex); - - if ($self->FilesProvider()->PutFile($oAccount, $sTempName, $rResource)) - { - $mResult[$sTempName] = $sAttachment; - } - } - }, $sFolder, $iUid, true, $sMimeIndex); - } - else - { - $mResult[$sTempName] = $sAttachment; - } - } - } - } - } - catch (\Throwable $oException) - { - throw new Exceptions\ClientException(Notifications::MailServerError, $oException); - } - - return $this->DefaultResponse(__FUNCTION__, $mResult); - } - - public function DoComposeUploadExternals() : array - { - $oAccount = $this->getAccountFromToken(); - - $mResult = false; - $aExternals = $this->GetActionParam('Externals', array()); - if (\is_array($aExternals) && 0 < \count($aExternals)) - { - $oHttp = \MailSo\Base\Http::SingletonInstance(); - - $mResult = array(); - foreach ($aExternals as $sUrl) - { - $mResult[$sUrl] = ''; - - $sTempName = \md5($sUrl); - - $iCode = 0; - $sContentType = ''; - - $rFile = $this->FilesProvider()->GetFile($oAccount, $sTempName, 'wb+'); - if ($rFile && $oHttp->SaveUrlToFile($sUrl, $rFile, '', $sContentType, $iCode, $this->Logger(), 60, - $this->Config()->Get('labs', 'curl_proxy', ''), $this->Config()->Get('labs', 'curl_proxy_auth', ''))) - { - $mResult[$sUrl] = $sTempName; - } - - if (\is_resource($rFile)) - { - \fclose($rFile); - } - } - } - - return $this->DefaultResponse(__FUNCTION__, $mResult); - } - private function getUploadErrorMessageByCode(int $iError, int &$iClientError) : string { $sError = ''; @@ -5366,31 +3064,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return $this->DefaultResponse(__FUNCTION__, $aResponse); } - public function DoClearUserBackground() : array - { - $oAccount = $this->getAccountFromToken(); - - if (!$this->GetCapa(false, false, Enumerations\Capa::USER_BACKGROUND, $oAccount)) - { - return $this->FalseResponse(__FUNCTION__); - } - - $oSettings = $this->SettingsProvider()->Load($oAccount); - if ($oAccount && $oSettings) - { - $this->StorageProvider()->Clear($oAccount, - Providers\Storage\Enumerations\StorageType::CONFIG, - 'background' - ); - - $oSettings->SetConf('UserBackgroundName', ''); - $oSettings->SetConf('UserBackgroundHash', ''); - } - - return $this->DefaultResponse(__FUNCTION__, $oAccount && $oSettings ? - $this->SettingsProvider()->Save($oAccount, $oSettings) : false); - } - public function UploadBackground() : array { $oAccount = $this->getAccountFromToken(); @@ -5655,48 +3328,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut }, $sFolder, $iUid, true, $sMimeIndex); } - public function RawFramedView() : string - { - $oAccount = $this->getAccountFromToken(false); - if ($oAccount) - { - $sRawKey = (string) $this->GetActionParam('RawKey', ''); - $aParams = $this->GetActionParam('Params', null); - $this->Http()->ServerNoCache(); - - $aData = Utils::DecodeKeyValuesQ($sRawKey); - if (isset($aParams[0], $aParams[1], $aParams[2]) && - 'Raw' === $aParams[0] && 'FramedView' === $aParams[2] && isset($aData['Framed']) && $aData['Framed'] && $aData['FileName']) - { - if ($this->isFileHasFramedPreview($aData['FileName'])) - { - $sNewSpecAuthToken = $this->GetShortLifeSpecAuthToken(); - if (!empty($sNewSpecAuthToken)) - { - $aParams[1] = '_'.$sNewSpecAuthToken; - $aParams[2] = 'View'; - - \array_shift($aParams); - $sLast = \array_pop($aParams); - - $sUrl = $this->Http()->GetFullUrl().'?/Raw/&q[]=/'.\implode('/', $aParams).'/&q[]=/'.$sLast; - $sFullUrl = 'https://docs.google.com/viewer?embedded=true&url='.\urlencode($sUrl); - - \header('Content-Type: text/html; charset=utf-8'); - echo '
'. - ''. - ''. - ''; - } - } - } - } - - - return true; - - } - /** * @throws \MailSo\Base\Exceptions\Exception */ @@ -6338,46 +3969,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return false; } - public function isFileHasFramedPreview(string $sFileName) : bool - { - $sExt = \MailSo\Base\Utils::GetFileExtension($sFileName); - return \in_array($sExt, array('doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx')); - } - - public function isFileHasThumbnail(string $sFileName) : bool - { - static $aCache = array(); - - $sExt = \MailSo\Base\Utils::GetFileExtension($sFileName); - if (isset($aCache[$sExt])) - { - return $aCache[$sExt]; - } - - $bResult = \function_exists('gd_info'); - if ($bResult) - { - $bResult = false; - switch ($sExt) - { - case 'png': - $bResult = \function_exists('imagecreatefrompng'); - break; - case 'gif': - $bResult = \function_exists('imagecreatefromgif'); - break; - case 'jpg': - case 'jpeg': - $bResult = \function_exists('imagecreatefromjpeg'); - break; - } - } - - $aCache[$sExt] = $bResult; - - return $bResult; - } - public function RawContactsVcf() : bool { $oAccount = $this->getAccountFromToken(); @@ -6678,109 +4269,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return Utils::ClearHtmlOutput($sHtml); } - /** - * @param mixed $mResult = false - */ - private function mainDefaultResponse(string $sActionName, $mResult = false, array $aAdditionalParams = array()) : array - { - $sActionName = 'Do' === \substr($sActionName, 0, 2) ? \substr($sActionName, 2) : $sActionName; - $sActionName = \preg_replace('/[^a-zA-Z0-9_]+/', '', $sActionName); - - $aResult = array( - 'Action' => $sActionName, - 'Result' => $this->responseObject($mResult, $sActionName) - ); - - foreach ($aAdditionalParams as $sKey => $mValue) - { - $aResult[$sKey] = $mValue; - } - - return $aResult; - } - /** - * @param mixed $mResult = false - */ - public function DefaultResponse(string $sActionName, $mResult = false, array $aAdditionalParams = array()) : array - { - $this->Plugins()->RunHook('main.default-response-data', array($sActionName, &$mResult)); - $aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams); - $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); - return $aResponseItem; - } - - public function TrueResponse(string $sActionName, array $aAdditionalParams = array()) : array - { - $mResult = true; - $this->Plugins()->RunHook('main.default-response-data', array($sActionName, &$mResult)); - $aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams); - $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); - return $aResponseItem; - } - - public function FalseResponse(string $sActionName, ?int $iErrorCode = null, ?string $sErrorMessage = null, ?string $sAdditionalErrorMessage = null) : array - { - $mResult = false; - $this->Plugins() - ->RunHook('main.default-response-data', array($sActionName, &$mResult)) - ->RunHook('main.default-response-error-data', array($sActionName, &$iErrorCode, &$sErrorMessage)) - ; - - $aAdditionalParams = array(); - if (null !== $iErrorCode) - { - $aAdditionalParams['ErrorCode'] = (int) $iErrorCode; - $aAdditionalParams['ErrorMessage'] = null === $sErrorMessage ? '' : (string) $sErrorMessage; - $aAdditionalParams['ErrorMessageAdditional'] = null === $sAdditionalErrorMessage ? '' : (string) $sAdditionalErrorMessage; - } - - $aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams); - - $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); - return $aResponseItem; - } - - public function ExceptionResponse(string $sActionName, \Throwable $oException) : array - { - $iErrorCode = null; - $sErrorMessage = null; - $sErrorMessageAdditional = null; - - if ($oException instanceof Exceptions\ClientException) - { - $iErrorCode = $oException->getCode(); - $sErrorMessage = null; - - if ($iErrorCode === Notifications::ClientViewError) - { - $sErrorMessage = $oException->getMessage(); - } - - $sErrorMessageAdditional = $oException->getAdditionalMessage(); - if (empty($sErrorMessageAdditional)) - { - $sErrorMessageAdditional = null; - } - } - else - { - $iErrorCode = Notifications::UnknownError; - $sErrorMessage = $oException->getCode().' - '.$oException->getMessage(); - } - - $oPrevious = $oException->getPrevious(); - if ($oPrevious) - { - $this->Logger()->WriteException($oPrevious); - } - else - { - $this->Logger()->WriteException($oException); - } - - return $this->FalseResponse($sActionName, $iErrorCode, $sErrorMessage, $sErrorMessageAdditional); - } - public function SetActionParams(array $aCurrentActionParams, string $sMethodName = '') : self { $this->Plugins()->RunHook('filter.action-params', array($sMethodName, &$aCurrentActionParams)); @@ -6833,38 +4321,6 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut \header('Location: '.$sUrl); } - private function objectData(object $oData, string $sParent, array $aParameters = array()) : array - { - $mResult = array(); - if (is_object($oData)) - { - $aNames = explode('\\', get_class($oData)); - $mResult = array( - '@Object' => end($aNames) - ); - - if ($oData instanceof \MailSo\Base\Collection) - { - $mResult['@Object'] = 'Collection/'.$mResult['@Object']; - $mResult['@Count'] = $oData->Count(); - $mResult['@Collection'] = $this->responseObject($oData->getArrayCopy(), $sParent, $aParameters); - } - else - { - $mResult['@Object'] = 'Object/'.$mResult['@Object']; - } - } - - return $mResult; - } - - private function hashFolderFullName(string $sFolderFullName) : string - { - return \in_array(\strtolower($sFolderFullName), array('inbox', 'sent', 'send', 'drafts', - 'spam', 'junk', 'bin', 'trash', 'archive', 'allmail', 'all')) ? - $sFolderFullName : \md5($sFolderFullName); - } - public function GetLanguageAndTheme(bool $bAdmin = false, bool $bMobile = false) : array { $sTheme = $this->Config()->Get('webmail', 'theme', 'Default'); @@ -6995,436 +4451,4 @@ NewThemeLink IncludeCss TemplatesLink LangLink IncludeBackground PluginsLink Aut return $aResult; } - /** - * @param mixed $mResponse - * - * @return mixed - */ - protected $oAccount = null; - protected $aCheckableFolder = null; - protected function responseObject($mResponse, string $sParent = '', array $aParameters = array()) - { - if (\is_object($mResponse)) - { - $bHook = true; - $sClassName = \get_class($mResponse); - if (\method_exists($mResponse, 'ToSimpleJSON')) - { - $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), $mResponse->ToSimpleJSON(true)); - } - else if ('MailSo\Mail\Message' === $sClassName) - { - if (null === $this->oAccount) { - $this->oAccount = $this->getAccountFromToken(false); - } - $oAccount = $this->oAccount; - - $iDateTimeStampInUTC = $mResponse->InternalTimeStampInUTC(); - if (0 === $iDateTimeStampInUTC || !!$this->Config()->Get('labs', 'date_from_headers', false)) - { - $iDateTimeStampInUTC = $mResponse->HeaderTimeStampInUTC(); - if (0 === $iDateTimeStampInUTC) - { - $iDateTimeStampInUTC = $mResponse->InternalTimeStampInUTC(); - } - } - - $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array( - 'Folder' => $mResponse->Folder(), - 'Uid' => (string) $mResponse->Uid(), - 'Subject' => \trim(\MailSo\Base\Utils::Utf8Clear($mResponse->Subject())), - 'MessageId' => $mResponse->MessageId(), - 'Size' => $mResponse->Size(), - 'DateTimeStampInUTC' => $iDateTimeStampInUTC, - 'ReplyTo' => $this->responseObject($mResponse->ReplyTo(), $sParent, $aParameters), - 'From' => $this->responseObject($mResponse->From(), $sParent, $aParameters), - 'To' => $this->responseObject($mResponse->To(), $sParent, $aParameters), - 'Cc' => $this->responseObject($mResponse->Cc(), $sParent, $aParameters), - 'Bcc' => $this->responseObject($mResponse->Bcc(), $sParent, $aParameters), - 'Sender' => $this->responseObject($mResponse->Sender(), $sParent, $aParameters), - 'DeliveredTo' => $this->responseObject($mResponse->DeliveredTo(), $sParent, $aParameters), - 'Priority' => $mResponse->Priority(), - 'Threads' => $mResponse->Threads(), - 'Sensitivity' => $mResponse->Sensitivity(), - 'UnsubsribeLinks' => $mResponse->UnsubsribeLinks(), - 'ExternalProxy' => false, - 'ReadReceipt' => '' - )); - - $mResult['SubjectParts'] = $this->explodeSubject($mResult['Subject']); - - $oAttachments = $mResponse->Attachments(); - $iAttachmentsCount = $oAttachments ? $oAttachments->Count() : 0; - - $mResult['HasAttachments'] = 0 < $iAttachmentsCount; - $mResult['AttachmentsSpecData'] = $mResult['HasAttachments'] ? $oAttachments->SpecData() : array(); - - $sSubject = $mResult['Subject']; - $mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']); - $mResult['RequestHash'] = Utils::EncodeKeyValuesQ(array( - 'V' => APP_VERSION, - 'Account' => $oAccount ? \md5($oAccount->Hash()) : '', - 'Folder' => $mResult['Folder'], - 'Uid' => $mResult['Uid'], - 'MimeType' => 'message/rfc822', - 'FileName' => (0 === \strlen($sSubject) ? 'message-'.$mResult['Uid'] : \MailSo\Base\Utils::ClearXss($sSubject)).'.eml' - )); - - // Flags - $aFlags = $mResponse->FlagsLowerCase(); - $mResult['IsSeen'] = \in_array('\\seen', $aFlags); - $mResult['IsFlagged'] = \in_array('\\flagged', $aFlags); - $mResult['IsAnswered'] = \in_array('\\answered', $aFlags); - $mResult['IsDeleted'] = \in_array('\\deleted', $aFlags); - - $sForwardedFlag = $this->Config()->Get('labs', 'imap_forwarded_flag', ''); - $sReadReceiptFlag = $this->Config()->Get('labs', 'imap_read_receipt_flag', ''); - - $mResult['IsForwarded'] = 0 < \strlen($sForwardedFlag) && \in_array(\strtolower($sForwardedFlag), $aFlags); - $mResult['IsReadReceipt'] = 0 < \strlen($sReadReceiptFlag) && \in_array(\strtolower($sReadReceiptFlag), $aFlags); - - if (!$this->GetCapa(false, false, Enumerations\Capa::COMPOSER, $oAccount)) - { - $mResult['IsReadReceipt'] = true; - } - - $mResult['TextPartIsTrimmed'] = false; - - if ('Message' === $sParent) - { - $oAttachments = /* @var \MailSo\Mail\AttachmentCollection */ $mResponse->Attachments(); - - $bHasExternals = false; - $mFoundedCIDs = array(); - $aContentLocationUrls = array(); - $mFoundedContentLocationUrls = array(); - - if ($oAttachments && 0 < $oAttachments->Count()) - { - foreach ($oAttachments as /* @var \MailSo\Mail\Attachment */ $oAttachment) - { - if ($oAttachment) - { - $sContentLocation = $oAttachment->ContentLocation(); - if ($sContentLocation && 0 < \strlen($sContentLocation)) - { - $aContentLocationUrls[] = $oAttachment->ContentLocation(); - } - } - } - } - - $sPlain = ''; - $sHtml = \trim($mResponse->Html()); - - if (0 === \strlen($sHtml)) - { - $sPlain = \trim($mResponse->Plain()); - } - - $mResult['DraftInfo'] = $mResponse->DraftInfo(); - $mResult['InReplyTo'] = $mResponse->InReplyTo(); - $mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks(); - $mResult['References'] = $mResponse->References(); - - $fAdditionalExternalFilter = null; - if (!!$this->Config()->Get('labs', 'use_local_proxy_for_external_images', false)) - { - $fAdditionalExternalFilter = function ($sUrl) { - return './?/ProxyExternal/'.Utils::EncodeKeyValuesQ(array( - 'Rnd' => \md5(\microtime(true)), - 'Token' => Utils::GetConnectionToken(), - 'Url' => $sUrl - )).'/'; - }; - } - - $sHtml = \preg_replace_callback('/(]*>)([\s\S\r\n\t]*?)(<\/pre>)/mi', function ($aMatches) {
- return \preg_replace('/[\r\n]+/', '
', $aMatches[1].\trim($aMatches[2]).$aMatches[3]);
- }, $sHtml);
-
- $mResult['Html'] = 0 === \strlen($sHtml) ? '' : \MailSo\Base\HtmlUtils::ClearHtml(
- $sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls, false, false,
- $fAdditionalExternalFilter, null, !!$this->Config()->Get('labs', 'try_to_detect_hidden_images', false)
- );
-
- $mResult['ExternalProxy'] = null !== $fAdditionalExternalFilter;
-
- $mResult['Plain'] = $sPlain;
-// $mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain);
-
- $mResult['TextHash'] = \md5($mResult['Html'].$mResult['Plain']);
-
- $mResult['TextPartIsTrimmed'] = $mResponse->TextPartIsTrimmed();
-
- $mResult['PgpSigned'] = $mResponse->PgpSigned();
- $mResult['PgpEncrypted'] = $mResponse->PgpEncrypted();
- $mResult['PgpSignature'] = $mResponse->PgpSignature();
-
- unset($sHtml, $sPlain);
-
- $mResult['HasExternals'] = $bHasExternals;
- $mResult['HasInternals'] = (\is_array($mFoundedCIDs) && 0 < \count($mFoundedCIDs)) ||
- (\is_array($mFoundedContentLocationUrls) && 0 < \count($mFoundedContentLocationUrls));
- $mResult['FoundedCIDs'] = $mFoundedCIDs;
- $mResult['Attachments'] = $this->responseObject($oAttachments, $sParent, \array_merge($aParameters, array(
- 'FoundedCIDs' => $mFoundedCIDs,
- 'FoundedContentLocationUrls' => $mFoundedContentLocationUrls
- )));
-
- $mResult['ReadReceipt'] = $mResponse->ReadReceipt();
- if (0 < \strlen($mResult['ReadReceipt']) && !$mResult['IsReadReceipt'])
- {
- if (0 < \strlen($mResult['ReadReceipt']))
- {
- try
- {
- $oReadReceipt = \MailSo\Mime\Email::Parse($mResult['ReadReceipt']);
- if (!$oReadReceipt)
- {
- $mResult['ReadReceipt'] = '';
- }
- }
- catch (\Throwable $oException) { unset($oException); }
- }
-
- if (0 < \strlen($mResult['ReadReceipt']) && '1' === $this->Cacher($oAccount)->Get(
- KeyPathHelper::ReadReceiptCache($oAccount->Email(), $mResult['Folder'], $mResult['Uid']), '0'))
- {
- $mResult['ReadReceipt'] = '';
- }
- }
- }
- }
- else if ('MailSo\Mime\Email' === $sClassName)
- {
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- 'Name' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetDisplayName()),
- 'Email' => \MailSo\Base\Utils::Utf8Clear($mResponse->GetEmail(true)),
- 'DkimStatus' => $mResponse->GetDkimStatus(),
- 'DkimValue' => $mResponse->GetDkimValue()
- ));
- }
- else if ('RainLoop\Providers\AddressBook\Classes\Contact' === $sClassName)
- {
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- /* @var $mResponse Providers\AddressBook\Classes\Contact */
- 'IdContact' => $mResponse->IdContact,
- 'Display' => \MailSo\Base\Utils::Utf8Clear($mResponse->Display),
- 'ReadOnly' => $mResponse->ReadOnly,
- 'IdPropertyFromSearch' => $mResponse->IdPropertyFromSearch,
- 'Properties' => $this->responseObject($mResponse->Properties, $sParent, $aParameters)
- ));
- }
- else if ('RainLoop\Providers\AddressBook\Classes\Tag' === $sClassName)
- {
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- /* @var $mResponse Providers\AddressBook\Classes\Tag */
- 'IdContactTag' => $mResponse->IdContactTag,
- 'Name' => \MailSo\Base\Utils::Utf8Clear($mResponse->Name),
- 'ReadOnly' => $mResponse->ReadOnly
- ));
- }
- else if ('RainLoop\Providers\AddressBook\Classes\Property' === $sClassName)
- {
- // Simple hack
- if ($mResponse && $mResponse->IsWeb())
- {
- $mResponse->Value = \preg_replace('/(skype|ftp|http[s]?)\\\:\/\//i', '$1://', $mResponse->Value);
- }
-
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- /* @var $mResponse Providers\AddressBook\Classes\Property */
- 'IdProperty' => $mResponse->IdProperty,
- 'Type' => $mResponse->Type,
- 'TypeStr' => $mResponse->TypeStr,
- 'Value' => \MailSo\Base\Utils::Utf8Clear($mResponse->Value)
- ));
- }
- else if ('MailSo\Mail\Attachment' === $sClassName)
- {
- if (null === $this->oAccount) {
- $this->oAccount = $this->getAccountFromToken(false);
- }
-
- $mFoundedCIDs = isset($aParameters['FoundedCIDs']) && \is_array($aParameters['FoundedCIDs']) &&
- 0 < \count($aParameters['FoundedCIDs']) ?
- $aParameters['FoundedCIDs'] : null;
-
- $mFoundedContentLocationUrls = isset($aParameters['FoundedContentLocationUrls']) &&
- \is_array($aParameters['FoundedContentLocationUrls']) &&
- 0 < \count($aParameters['FoundedContentLocationUrls']) ?
- $aParameters['FoundedContentLocationUrls'] : null;
-
- if ($mFoundedCIDs || $mFoundedContentLocationUrls)
- {
- $mFoundedCIDs = \array_merge($mFoundedCIDs ? $mFoundedCIDs : array(),
- $mFoundedContentLocationUrls ? $mFoundedContentLocationUrls : array());
-
- $mFoundedCIDs = 0 < \count($mFoundedCIDs) ? $mFoundedCIDs : null;
- }
-
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- 'Folder' => $mResponse->Folder(),
- 'Uid' => (string) $mResponse->Uid(),
- 'Framed' => false,
- 'MimeIndex' => (string) $mResponse->MimeIndex(),
- 'MimeType' => $mResponse->MimeType(),
- 'FileName' => \MailSo\Base\Utils::ClearFileName(
- \MailSo\Base\Utils::ClearXss($mResponse->FileName(true))),
- 'EstimatedSize' => $mResponse->EstimatedSize(),
- 'CID' => $mResponse->Cid(),
- 'ContentLocation' => $mResponse->ContentLocation(),
- 'IsInline' => $mResponse->IsInline(),
- 'IsThumbnail' => $this->GetCapa(false, false, Enumerations\Capa::ATTACHMENT_THUMBNAILS),
- 'IsLinked' => ($mFoundedCIDs && \in_array(\trim(\trim($mResponse->Cid()), '<>'), $mFoundedCIDs)) ||
- ($mFoundedContentLocationUrls && \in_array(\trim($mResponse->ContentLocation()), $mFoundedContentLocationUrls))
- ));
-
- $mResult['Framed'] = $this->isFileHasFramedPreview($mResult['FileName']);
-
- if ($mResult['IsThumbnail'])
- {
- $mResult['IsThumbnail'] = $this->isFileHasThumbnail($mResult['FileName']);
- }
-
- $mResult['Download'] = Utils::EncodeKeyValuesQ(array(
- 'V' => APP_VERSION,
- 'Account' => $this->oAccount ? \md5($this->oAccount->Hash()) : '',
- 'Folder' => $mResult['Folder'],
- 'Uid' => $mResult['Uid'],
- 'MimeIndex' => $mResult['MimeIndex'],
- 'MimeType' => $mResult['MimeType'],
- 'FileName' => $mResult['FileName'],
- 'Framed' => $mResult['Framed']
- ));
- }
- else if ('MailSo\Mail\Folder' === $sClassName)
- {
- $aExtended = null;
-
-// $mStatus = $mResponse->Status();
-// if (\is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT']))
-// {
-// $aExtended = array(
-// 'MessageCount' => (int) $mStatus['MESSAGES'],
-// 'MessageUnseenCount' => (int) $mStatus['UNSEEN'],
-// 'UidNext' => (string) $mStatus['UIDNEXT'],
-// 'Hash' => $this->MailClient()->GenerateFolderHash(
-// $mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'],
-// empty($mStatus['HIGHESTMODSEQ']) ? '' : $mStatus['HIGHESTMODSEQ'])
-// );
-// }
-
- if (null === $this->aCheckableFolder)
- {
- if (null === $this->oAccount) {
- $this->oAccount = $this->getAccountFromToken(false);
- }
- $aCheckable = \json_decode(
- $this->SettingsProvider(true)
- ->Load($this->oAccount)
- ->GetConf('CheckableFolder', '[]')
- );
- $this->aCheckableFolder = \is_array($aCheckable) ? $aCheckable : array();
- }
-
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- 'Name' => $mResponse->Name(),
- 'FullName' => $mResponse->FullName(),
- 'FullNameRaw' => $mResponse->FullNameRaw(),
- 'FullNameHash' => $this->hashFolderFullName($mResponse->FullNameRaw(), $mResponse->FullName()),
- 'Delimiter' => (string) $mResponse->Delimiter(),
- 'HasVisibleSubFolders' => $mResponse->HasVisibleSubFolders(),
- 'IsSubscribed' => $mResponse->IsSubscribed(),
- 'IsExists' => $mResponse->IsExists(),
- 'IsSelectable' => $mResponse->IsSelectable(),
- 'Flags' => $mResponse->FlagsLowerCase(),
- 'Checkable' => \in_array($mResponse->FullNameRaw(), $this->aCheckableFolder),
- 'Extended' => $aExtended,
- 'SubFolders' => $this->responseObject($mResponse->SubFolders(), $sParent, $aParameters)
- ));
- }
- else if ('MailSo\Mail\MessageCollection' === $sClassName)
- {
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- 'MessageCount' => $mResponse->MessageCount,
- 'MessageUnseenCount' => $mResponse->MessageUnseenCount,
- 'MessageResultCount' => $mResponse->MessageResultCount,
- 'Folder' => $mResponse->FolderName,
- 'FolderHash' => $mResponse->FolderHash,
- 'UidNext' => $mResponse->UidNext,
- 'ThreadUid' => $mResponse->ThreadUid,
- 'NewMessages' => $this->responseObject($mResponse->NewMessages),
- 'Filtered' => $mResponse->Filtered,
- 'Offset' => $mResponse->Offset,
- 'Limit' => $mResponse->Limit,
- 'Search' => $mResponse->Search
- ));
- }
- else if ('MailSo\Mail\AttachmentCollection' === $sClassName)
- {
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- 'InlineCount' => $mResponse->InlineCount()
- ));
- }
- else if ('MailSo\Mail\FolderCollection' === $sClassName)
- {
- $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
- 'Namespace' => $mResponse->GetNamespace(),
- 'FoldersHash' => isset($mResponse->FoldersHash) ? $mResponse->FoldersHash : '',
- 'IsThreadsSupported' => $mResponse->IsThreadsSupported,
- 'Optimized' => $mResponse->Optimized,
- 'CountRec' => $mResponse->CountRec(),
- 'SystemFolders' => isset($mResponse->SystemFolders) && \is_array($mResponse->SystemFolders) ?
- $mResponse->SystemFolders : array()
- ));
- }
- else if ('MailSo\Mime\EmailCollection' === $sClassName)
- {
- $mResult = array();
- if (100 < \count($mResponse)) {
- $mResponse = $mResponse->Slice(0, 100);
- }
- foreach ($mResponse as $iKey => $oItem) {
- $mResult[$iKey] = $this->responseObject($oItem, $sParent, $aParameters);
- }
- $bHook = false;
- }
- else if ($mResponse instanceof \MailSo\Base\Collection)
- {
- $mResult = array();
- foreach ($mResponse as $iKey => $oItem) {
- $mResult[$iKey] = $this->responseObject($oItem, $sParent, $aParameters);
- }
- $bHook = false;
- }
- else
- {
- $mResult = '["'.$sClassName.'"]';
- $bHook = false;
- }
-
- if ($bHook)
- {
- $this->Plugins()->RunHook('filter.response-object', array($sClassName, $mResult), false);
- }
- }
- else if (\is_array($mResponse))
- {
- foreach ($mResponse as $iKey => $oItem)
- {
- $mResponse[$iKey] = $this->responseObject($oItem, $sParent, $aParameters);
- }
-
- $mResult = $mResponse;
- }
- else
- {
- $mResult = $mResponse;
- }
-
- unset($mResponse);
- return $mResult;
- }
}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php
new file mode 100644
index 000000000..2588f1a2c
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php
@@ -0,0 +1,217 @@
+getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::ADDITIONAL_ACCOUNTS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sParentEmail = $oAccount->ParentEmailHelper();
+
+ $aAccounts = $this->GetAccounts($oAccount);
+
+ $sEmail = \trim($this->GetActionParam('Email', ''));
+ $sPassword = $this->GetActionParam('Password', '');
+ $bNew = '1' === (string) $this->GetActionParam('New', '1');
+
+ $sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
+ if ($bNew && ($oAccount->Email() === $sEmail || $sParentEmail === $sEmail || isset($aAccounts[$sEmail])))
+ {
+ throw new ClientException(Notifications::AccountAlreadyExists);
+ }
+ else if (!$bNew && !isset($aAccounts[$sEmail]))
+ {
+ throw new ClientException(Notifications::AccountDoesNotExist);
+ }
+
+ $oNewAccount = $this->LoginProcess($sEmail, $sPassword, '', '', false, true);
+ $oNewAccount->SetParentEmail($sParentEmail);
+
+ $aAccounts[$oNewAccount->Email()] = $oNewAccount->GetAuthToken();
+ if (!$oAccount->IsAdditionalAccount())
+ {
+ $aAccounts[$oAccount->Email()] = $oAccount->GetAuthToken();
+ }
+
+ $this->SetAccounts($oAccount, $aAccounts);
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoAccountDelete() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::ADDITIONAL_ACCOUNTS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sParentEmail = $oAccount->ParentEmailHelper();
+ $sEmailToDelete = \trim($this->GetActionParam('EmailToDelete', ''));
+ $sEmailToDelete = \MailSo\Base\Utils::IdnToAscii($sEmailToDelete, true);
+
+ $aAccounts = $this->GetAccounts($oAccount);
+
+ if (0 < \strlen($sEmailToDelete) && $sEmailToDelete !== $sParentEmail && isset($aAccounts[$sEmailToDelete]))
+ {
+ unset($aAccounts[$sEmailToDelete]);
+
+ $oAccountToChange = null;
+ if ($oAccount->Email() === $sEmailToDelete && !empty($aAccounts[$sParentEmail]))
+ {
+ $oAccountToChange = $this->GetAccountFromCustomToken($aAccounts[$sParentEmail], false, false);
+ if ($oAccountToChange)
+ {
+ $this->AuthToken($oAccountToChange);
+ }
+ }
+
+ $this->SetAccounts($oAccount, $aAccounts);
+ return $this->TrueResponse(__FUNCTION__, array('Reload' => !!$oAccountToChange));
+ }
+
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoIdentityUpdate() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $oIdentity = new \RainLoop\Model\Identity();
+ if (!$oIdentity->FromJSON($this->GetActionParams(), true))
+ {
+ throw new ClientException(Notifications::InvalidInputArgument);
+ }
+
+ $aIdentities = $this->GetIdentities($oAccount);
+
+ $bAdded = false;
+ $aIdentitiesForSave = array();
+ foreach ($aIdentities as $oItem)
+ {
+ if ($oItem)
+ {
+ if ($oItem->Id() === $oIdentity->Id())
+ {
+ $aIdentitiesForSave[] = $oIdentity;
+ $bAdded = true;
+ }
+ else
+ {
+ $aIdentitiesForSave[] = $oItem;
+ }
+ }
+ }
+
+ if (!$bAdded)
+ {
+ $aIdentitiesForSave[] = $oIdentity;
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentitiesForSave));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoIdentityDelete() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::IDENTITIES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sId = \trim($this->GetActionParam('IdToDelete', ''));
+ if (empty($sId))
+ {
+ throw new ClientException(Notifications::UnknownError);
+ }
+
+ $aNew = array();
+ $aIdentities = $this->GetIdentities($oAccount);
+
+ foreach ($aIdentities as $oItem)
+ {
+ if ($oItem && $sId !== $oItem->Id())
+ {
+ $aNew[] = $oItem;
+ }
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aNew));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoAccountsAndIdentitiesSortOrder() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $aAccounts = $this->GetActionParam('Accounts', null);
+ $aIdentities = $this->GetActionParam('Identities', null);
+
+ if (!\is_array($aAccounts) && !\is_array($aIdentities))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $this->StorageProvider()->Put($oAccount,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG, 'accounts_identities_order',
+ \json_encode(array(
+ 'Accounts' => \is_array($aAccounts) ? $aAccounts : array(),
+ 'Identities' => \is_array($aIdentities) ? $aIdentities : array()
+ ))
+ ));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoAccountsAndIdentities() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $mAccounts = false;
+
+ if ($this->GetCapa(false, false, Capa::ADDITIONAL_ACCOUNTS, $oAccount))
+ {
+ $mAccounts = $this->GetAccounts($oAccount);
+ $mAccounts = \array_keys($mAccounts);
+
+ foreach ($mAccounts as $iIndex => $sName)
+ {
+ $mAccounts[$iIndex] = \MailSo\Base\Utils::IdnToUtf8($sName);
+ }
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, array(
+ 'Accounts' => $mAccounts,
+ 'Identities' => $this->GetIdentities($oAccount)
+ ));
+ }
+
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php
new file mode 100644
index 000000000..44aca9f4d
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php
@@ -0,0 +1,176 @@
+getAccountFromToken();
+
+ $oAddressBookProvider = $this->AddressBookProvider($oAccount);
+ if (!$oAddressBookProvider || !$oAddressBookProvider->IsActive())
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $bEnabled = '1' === (string) $this->GetActionParam('Enable', '0');
+ $sUrl = $this->GetActionParam('Url', '');
+ $sUser = $this->GetActionParam('User', '');
+ $sPassword = $this->GetActionParam('Password', '');
+
+ $mData = $this->getContactsSyncData($oAccount);
+
+ $bResult = $this->StorageProvider()->Put($oAccount,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
+ 'contacts_sync',
+ \RainLoop\Utils::EncodeKeyValues(array(
+ 'Enable' => $bEnabled,
+ 'User' => $sUser,
+ 'Password' => APP_DUMMY === $sPassword && isset($mData['Password']) ?
+ $mData['Password'] : (APP_DUMMY === $sPassword ? '' : $sPassword),
+ 'Url' => $sUrl
+ ))
+ );
+
+ return $this->DefaultResponse(__FUNCTION__, $bResult);
+ }
+
+ public function DoContactsSync() : array
+ {
+ $bResult = false;
+ $oAccount = $this->getAccountFromToken();
+
+ $oAddressBookProvider = $this->AddressBookProvider($oAccount);
+ if ($oAddressBookProvider && $oAddressBookProvider->IsActive())
+ {
+ $mData = $this->getContactsSyncData($oAccount);
+ if (isset($mData['Enable'], $mData['User'], $mData['Password'], $mData['Url']) && $mData['Enable'])
+ {
+ $bResult = $oAddressBookProvider->Sync(
+ $oAccount->ParentEmailHelper(),
+ $mData['Url'], $mData['User'], $mData['Password']);
+ }
+ }
+
+ if (!$bResult)
+ {
+ throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ContactsSyncError);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoContacts() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $sSearch = \trim($this->GetActionParam('Search', ''));
+ $iOffset = (int) $this->GetActionParam('Offset', 0);
+ $iLimit = (int) $this->GetActionParam('Limit', 20);
+ $iOffset = 0 > $iOffset ? 0 : $iOffset;
+ $iLimit = 0 > $iLimit ? 20 : $iLimit;
+
+ $iResultCount = 0;
+ $mResult = array();
+
+ $oAbp = $this->AddressBookProvider($oAccount);
+ if ($oAbp->IsActive())
+ {
+ $iResultCount = 0;
+ $mResult = $oAbp->GetContacts($oAccount->ParentEmailHelper(),
+ $iOffset, $iLimit, $sSearch, $iResultCount);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, array(
+ 'Offset' => $iOffset,
+ 'Limit' => $iLimit,
+ 'Count' => $iResultCount,
+ 'Search' => $sSearch,
+ 'List' => $mResult
+ ));
+ }
+
+ public function DoContactsDelete() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+ $aUids = \explode(',', (string) $this->GetActionParam('Uids', ''));
+
+ $aFilteredUids = \array_filter($aUids, function (&$mUid) {
+ $mUid = (int) \trim($mUid);
+ return 0 < $mUid;
+ });
+
+ $bResult = false;
+ if (0 < \count($aFilteredUids) && $this->AddressBookProvider($oAccount)->IsActive())
+ {
+ $bResult = $this->AddressBookProvider($oAccount)->DeleteContacts($oAccount->ParentEmailHelper(), $aFilteredUids);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $bResult);
+ }
+
+ public function DoContactSave() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $bResult = false;
+
+ $oAddressBookProvider = $this->AddressBookProvider($oAccount);
+ $sRequestUid = \trim($this->GetActionParam('RequestUid', ''));
+ if ($oAddressBookProvider && $oAddressBookProvider->IsActive() && 0 < \strlen($sRequestUid))
+ {
+ $sUid = \trim($this->GetActionParam('Uid', ''));
+
+ $oContact = null;
+ if (0 < \strlen($sUid))
+ {
+ $oContact = $oAddressBookProvider->GetContactByID($oAccount->ParentEmailHelper(), $sUid);
+ }
+
+ if (!$oContact)
+ {
+ $oContact = new \RainLoop\Providers\AddressBook\Classes\Contact();
+ if (0 < \strlen($sUid))
+ {
+ $oContact->IdContact = $sUid;
+ }
+ }
+
+ $oContact->Properties = array();
+ $aProperties = $this->GetActionParam('Properties', array());
+ if (\is_array($aProperties))
+ {
+ foreach ($aProperties as $aItem)
+ {
+ if ($aItem && isset($aItem[0], $aItem[1]) && \is_numeric($aItem[0]))
+ {
+ $oProp = new \RainLoop\Providers\AddressBook\Classes\Property();
+ $oProp->Type = (int) $aItem[0];
+ $oProp->Value = $aItem[1];
+ $oProp->TypeStr = empty($aItem[2]) ? '': $aItem[2];
+
+ $oContact->Properties[] = $oProp;
+ }
+ }
+ }
+
+ if (!empty($oContact->Etag))
+ {
+ $oContact->Etag = \md5($oContact->ToVCard());
+ }
+
+ $oContact->PopulateDisplayAndFullNameValue(true);
+
+ $bResult = $oAddressBookProvider->ContactSave($oAccount->ParentEmailHelper(), $oContact);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, array(
+ 'RequestUid' => $sRequestUid,
+ 'ResultID' => $bResult ? $oContact->IdContact : '',
+ 'Result' => $bResult
+ ));
+ }
+
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Filters.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Filters.php
new file mode 100644
index 000000000..54736e307
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Filters.php
@@ -0,0 +1,74 @@
+getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::FILTERS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $aFakeFilters = null;
+
+ $this->Plugins()
+ ->RunHook('filter.filters-fake', array($oAccount, &$aFakeFilters))
+ ;
+
+ if ($aFakeFilters)
+ {
+ return $this->DefaultResponse(__FUNCTION__, $aFakeFilters);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__,
+ $this->FiltersProvider()->Load($oAccount, $oAccount->DomainSieveAllowRaw()));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoFiltersSave() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::FILTERS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $aIncFilters = $this->GetActionParam('Filters', array());
+
+ $sRaw = $this->GetActionParam('Raw', '');
+ $bRawIsActive = '1' === (string) $this->GetActionParam('RawIsActive', '0');
+
+ $aFilters = array();
+ foreach ($aIncFilters as $aFilter)
+ {
+ if (is_array($aFilter))
+ {
+ $oFilter = new \RainLoop\Providers\Filters\Classes\Filter();
+ if ($oFilter->FromJSON($aFilter))
+ {
+ $aFilters[] = $oFilter;
+ }
+ }
+ }
+
+ $this->Plugins()
+ ->RunHook('filter.filters-save', array($oAccount, &$aFilters, &$sRaw, &$bRawIsActive))
+ ;
+
+ return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->Save($oAccount,
+ $aFilters, $sRaw, $bRawIsActive));
+ }
+
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php
new file mode 100644
index 000000000..9e06caa7f
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php
@@ -0,0 +1,451 @@
+initMailClientConnection();
+
+ $oFolderCollection = null;
+ $this->Plugins()->RunHook('filter.folders-before', array($oAccount, $oFolderCollection));
+
+ $bUseFolders = $this->GetCapa(false, false, Capa::FOLDERS, $oAccount);
+
+ if (null === $oFolderCollection)
+ {
+ $oFolderCollection = $this->MailClient()->Folders('',
+ $bUseFolders ? '*' : 'INBOX',
+ !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true),
+ (int) $this->Config()->Get('labs', 'imap_folder_list_limit', 200)
+ );
+ }
+
+ $this->Plugins()->RunHook('filter.folders-post', array($oAccount, $oFolderCollection));
+
+ if ($oFolderCollection instanceof \MailSo\Mail\FolderCollection)
+ {
+ $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
+
+ $aSystemFolders = array();
+ $this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders);
+ $oFolderCollection->SystemFolders = $aSystemFolders;
+
+ if ($bUseFolders && $this->Config()->Get('labs', 'autocreate_system_folders', true))
+ {
+ $bDoItAgain = false;
+
+ $sNamespace = $oFolderCollection->GetNamespace();
+ $sParent = empty($sNamespace) ? '' : \substr($sNamespace, 0, -1);
+
+ $sDelimiter = $oFolderCollection->FindDelimiter();
+
+ $aList = array();
+ $aMap = $this->systemFoldersNames($oAccount);
+
+ if ('' === $oSettingsLocal->GetConf('SentFolder', ''))
+ {
+ $aList[] = FolderType::SENT;
+ }
+
+ if ('' === $oSettingsLocal->GetConf('DraftFolder', ''))
+ {
+ $aList[] = FolderType::DRAFTS;
+ }
+
+ if ('' === $oSettingsLocal->GetConf('SpamFolder', ''))
+ {
+ $aList[] = FolderType::JUNK;
+ }
+
+ if ('' === $oSettingsLocal->GetConf('TrashFolder', ''))
+ {
+ $aList[] = FolderType::TRASH;
+ }
+
+ if ('' === $oSettingsLocal->GetConf('ArchiveFolder', ''))
+ {
+ $aList[] = FolderType::ALL;
+ }
+
+ $this->Plugins()->RunHook('filter.folders-system-types', array($oAccount, &$aList));
+
+ foreach ($aList as $iType)
+ {
+ if (!isset($aSystemFolders[$iType]))
+ {
+ $mFolderNameToCreate = \array_search($iType, $aMap);
+ if (!empty($mFolderNameToCreate))
+ {
+ $iPos = \strrpos($mFolderNameToCreate, $sDelimiter);
+ if (false !== $iPos)
+ {
+ $mNewParent = \substr($mFolderNameToCreate, 0, $iPos);
+ $mNewFolderNameToCreate = \substr($mFolderNameToCreate, $iPos + 1);
+ if (0 < \strlen($mNewFolderNameToCreate))
+ {
+ $mFolderNameToCreate = $mNewFolderNameToCreate;
+ }
+
+ if (0 < \strlen($mNewParent))
+ {
+ $sParent = 0 < \strlen($sParent) ? $sParent.$sDelimiter.$mNewParent : $mNewParent;
+ }
+ }
+
+ $sFullNameToCheck = \MailSo\Base\Utils::ConvertEncoding($mFolderNameToCreate,
+ \MailSo\Base\Enumerations\Charset::UTF_8, \MailSo\Base\Enumerations\Charset::UTF_7_IMAP);
+
+ if (0 < \strlen(\trim($sParent)))
+ {
+ $sFullNameToCheck = $sParent.$sDelimiter.$sFullNameToCheck;
+ }
+
+ if (!$oFolderCollection->GetByFullNameRaw($sFullNameToCheck))
+ {
+ try
+ {
+ if ($this->MailClient()->FolderCreate($mFolderNameToCreate, $sParent, true, $sDelimiter))
+ {
+ $bDoItAgain = true;
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ $this->Logger()->WriteException($oException);
+ }
+ }
+ }
+ }
+ }
+
+ if ($bDoItAgain)
+ {
+ $oFolderCollection = $this->MailClient()->Folders('', '*',
+ !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true),
+ (int) $this->Config()->Get('labs', 'imap_folder_list_limit', 200)
+ );
+
+ if ($oFolderCollection)
+ {
+ $aSystemFolders = array();
+ $this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders);
+ $oFolderCollection->SystemFolders = $aSystemFolders;
+ }
+ }
+ }
+
+ if ($oFolderCollection)
+ {
+ $oFolderCollection->FoldersHash = \md5(\implode("\x0", $this->recFoldersNames($oFolderCollection)));
+ }
+ }
+
+ $this->Plugins()->RunHook('filter.folders-complete', array($oAccount, $oFolderCollection));
+
+ return $this->DefaultResponse(__FUNCTION__, $oFolderCollection);
+ }
+
+ public function DoFolderCreate() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ try
+ {
+ $sFolderNameInUtf = $this->GetActionParam('Folder', '');
+ $sFolderParentFullNameRaw = $this->GetActionParam('Parent', '');
+
+ $this->MailClient()->FolderCreate($sFolderNameInUtf, $sFolderParentFullNameRaw,
+ !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true));
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantCreateFolder, $oException);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoFolderSubscribe() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sFolderFullNameRaw = $this->GetActionParam('Folder', '');
+ $bSubscribe = '1' === (string) $this->GetActionParam('Subscribe', '0');
+
+ try
+ {
+ $this->MailClient()->FolderSubscribe($sFolderFullNameRaw, !!$bSubscribe);
+ }
+ catch (\Throwable $oException)
+ {
+ if ($bSubscribe)
+ {
+ throw new ClientException(Notifications::CantSubscribeFolder, $oException);
+ }
+ else
+ {
+ throw new ClientException(Notifications::CantUnsubscribeFolder, $oException);
+ }
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoFolderCheckable() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sFolderFullNameRaw = $this->GetActionParam('Folder', '');
+ $bCheckable = '1' === (string) $this->GetActionParam('Checkable', '0');
+
+ $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
+
+ $sCheckableFolder = $oSettingsLocal->GetConf('CheckableFolder', '[]');
+ $aCheckableFolder = \json_decode($sCheckableFolder);
+
+ if (!\is_array($aCheckableFolder))
+ {
+ $aCheckableFolder = array();
+ }
+
+ if ($bCheckable)
+ {
+ $aCheckableFolder[] = $sFolderFullNameRaw;
+ }
+ else
+ {
+ $aCheckableFolderNew = array();
+ foreach ($aCheckableFolder as $sFolder)
+ {
+ if ($sFolder !== $sFolderFullNameRaw)
+ {
+ $aCheckableFolderNew[] = $sFolder;
+ }
+ }
+ $aCheckableFolder = $aCheckableFolderNew;
+ }
+
+ $aCheckableFolder = \array_unique($aCheckableFolder);
+
+ $oSettingsLocal->SetConf('CheckableFolder', \json_encode($aCheckableFolder));
+
+ return $this->DefaultResponse(__FUNCTION__,
+ $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoFolderRename() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sPrevFolderFullNameRaw = $this->GetActionParam('Folder', '');
+ $sNewTopFolderNameInUtf = $this->GetActionParam('NewFolderName', '');
+
+ try
+ {
+ $this->MailClient()->FolderRename($sPrevFolderFullNameRaw, $sNewTopFolderNameInUtf,
+ !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true));
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantRenameFolder, $oException);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoFolderDelete() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Capa::FOLDERS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sFolderFullNameRaw = $this->GetActionParam('Folder', '');
+
+ try
+ {
+ $this->MailClient()->FolderDelete($sFolderFullNameRaw,
+ !!$this->Config()->Get('labs', 'use_imap_list_subscribe', true));
+ }
+ catch (\MailSo\Mail\Exceptions\NonEmptyFolder $oException)
+ {
+ throw new ClientException(Notifications::CantDeleteNonEmptyFolder, $oException);
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantDeleteFolder, $oException);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoFolderClear() : array
+ {
+ $this->initMailClientConnection();
+
+ $sFolderFullNameRaw = $this->GetActionParam('Folder', '');
+
+ try
+ {
+ $this->MailClient()->FolderClear($sFolderFullNameRaw);
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::MailServerError, $oException);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoFolderInformation() : array
+ {
+ $sFolder = $this->GetActionParam('Folder', '');
+ $sPrevUidNext = $this->GetActionParam('UidNext', '');
+ $aFlagsUids = array();
+ $sFlagsUids = (string) $this->GetActionParam('FlagsUids', '');
+
+ $aFlagsFilteredUids = array();
+ if (0 < strlen($sFlagsUids))
+ {
+ $aFlagsUids = explode(',', $sFlagsUids);
+ $aFlagsFilteredUids = array_filter($aFlagsUids, function (&$sUid) {
+ $sUid = (int) trim($sUid);
+ return 0 < (int) trim($sUid);
+ });
+ }
+
+ $this->initMailClientConnection();
+
+ $sForwardedFlag = $this->Config()->Get('labs', 'imap_forwarded_flag', '');
+ $sReadReceiptFlag = $this->Config()->Get('labs', 'imap_read_receipt_flag', '');
+ try
+ {
+ $aInboxInformation = $this->MailClient()->FolderInformation(
+ $sFolder, $sPrevUidNext, $aFlagsFilteredUids
+ );
+
+ if (isset($aInboxInformation['Flags']) && \is_array($aInboxInformation['Flags']))
+ {
+ foreach ($aInboxInformation['Flags'] as $iUid => $aFlags)
+ {
+ $aLowerFlags = array_map('strtolower', $aFlags);
+ $aInboxInformation['Flags'][$iUid] = array(
+ 'IsSeen' => in_array('\\seen', $aLowerFlags),
+ 'IsFlagged' => in_array('\\flagged', $aLowerFlags),
+ 'IsAnswered' => in_array('\\answered', $aLowerFlags),
+ 'IsDeleted' => in_array('\\deleted', $aLowerFlags),
+ 'IsForwarded' => 0 < strlen($sForwardedFlag) && in_array(strtolower($sForwardedFlag), $aLowerFlags),
+ 'IsReadReceipt' => 0 < strlen($sReadReceiptFlag) && in_array(strtolower($sReadReceiptFlag), $aLowerFlags)
+ );
+ }
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::MailServerError, $oException);
+ }
+
+ $aInboxInformation['Version'] = APP_VERSION;
+
+ return $this->DefaultResponse(__FUNCTION__, $aInboxInformation);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoFolderInformationMultiply() : array
+ {
+ $aResult = array(
+ 'List' => array(),
+ 'Version' => APP_VERSION
+ );
+
+ $aFolders = $this->GetActionParam('Folders', null);
+ if (\is_array($aFolders))
+ {
+ $this->initMailClientConnection();
+
+ $aFolders = \array_unique($aFolders);
+ foreach ($aFolders as $sFolder)
+ {
+ if (0 < \strlen(\trim($sFolder)) && 'INBOX' !== \strtoupper($sFolder))
+ {
+ try
+ {
+ $aInboxInformation = $this->MailClient()->FolderInformation($sFolder, '', array());
+ if (isset($aInboxInformation['Folder']))
+ {
+ $aResult['List'][] = $aInboxInformation;
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ $this->Logger()->WriteException($oException);
+ }
+ }
+ }
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $aResult);
+ }
+
+ public function DoSystemFoldersUpdate() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
+
+ $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(true)->Save($oAccount, $oSettingsLocal));
+ }
+
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php
new file mode 100644
index 000000000..86a66bf21
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php
@@ -0,0 +1,701 @@
+GetActionParam('RawKey', '');
+ $aValues = $this->getDecodedClientRawKeyValue($sRawKey, 9);
+
+ if ($aValues && 7 < \count($aValues))
+ {
+ $sFolder =(string) $aValues[0];
+ $iOffset = (int) $aValues[1];
+ $iLimit = (int) $aValues[2];
+ $sSearch = (string) $aValues[3];
+ $sUidNext = (string) $aValues[6];
+ $bUseThreads = (bool) $aValues[7];
+
+ if ($bUseThreads)
+ {
+ $sThreadUid = isset($aValues[8]) ? (string) $aValues[8] : '';
+ }
+
+ $this->verifyCacheByKey($sRawKey);
+ }
+ else
+ {
+ $sFolder = $this->GetActionParam('Folder', '');
+ $iOffset = (int) $this->GetActionParam('Offset', 0);
+ $iLimit = (int) $this->GetActionParam('Limit', 10);
+ $sSearch = $this->GetActionParam('Search', '');
+ $sUidNext = $this->GetActionParam('UidNext', '');
+ $bUseThreads = '1' === (string) $this->GetActionParam('UseThreads', '0');
+
+ if ($bUseThreads)
+ {
+ $sThreadUid = (string) $this->GetActionParam('ThreadUid', '');
+ }
+ }
+
+ if (0 === strlen($sFolder))
+ {
+ throw new ClientException(Notifications::CantGetMessageList);
+ }
+
+ $this->initMailClientConnection();
+
+ try
+ {
+ if (!$this->Config()->Get('labs', 'use_imap_thread', false))
+ {
+ $bUseThreads = false;
+ }
+
+ $oMessageList = $this->MailClient()->MessageList(
+ $sFolder, $iOffset, $iLimit, $sSearch, $sUidNext,
+ $this->cacherForUids(),
+ !!$this->Config()->Get('labs', 'use_imap_sort', false),
+ $bUseThreads,
+ $sThreadUid,
+ ''
+ );
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantGetMessageList, $oException);
+ }
+
+ if ($oMessageList)
+ {
+ $this->cacheByKey($sRawKey);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $oMessageList);
+ }
+
+ public function DoSaveMessage() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sMessageFolder = $this->GetActionParam('MessageFolder', '');
+ $sMessageUid = $this->GetActionParam('MessageUid', '');
+
+ $sDraftFolder = $this->GetActionParam('SaveFolder', '');
+ if (0 === strlen($sDraftFolder))
+ {
+ throw new ClientException(Notifications::UnknownError);
+ }
+
+ $oMessage = $this->buildMessage($oAccount, true);
+
+ $this->Plugins()->RunHook('filter.save-message', array($oMessage));
+
+ $mResult = false;
+ if ($oMessage)
+ {
+ $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
+
+ $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
+ $oMessage->ToStream(false), array($rMessageStream), 8192, true, true);
+
+ if (false !== $iMessageStreamSize)
+ {
+ $sMessageId = $oMessage->MessageId();
+
+ \rewind($rMessageStream);
+
+ $iNewUid = 0;
+ $this->MailClient()->MessageAppendStream(
+ $rMessageStream, $iMessageStreamSize, $sDraftFolder, array(
+ \MailSo\Imap\Enumerations\MessageFlag::SEEN
+ ), $iNewUid);
+
+ if (!empty($sMessageId) && (null === $iNewUid || 0 === $iNewUid))
+ {
+ $iNewUid = $this->MailClient()->FindMessageUidByMessageId($sDraftFolder, $sMessageId);
+ }
+
+ $mResult = true;
+
+ if (0 < strlen($sMessageFolder) && 0 < strlen($sMessageUid))
+ {
+ $this->MailClient()->MessageDelete($sMessageFolder, array($sMessageUid), true, true);
+ }
+
+ if (null !== $iNewUid && 0 < $iNewUid)
+ {
+ $mResult = array(
+ 'NewFolder' => $sDraftFolder,
+ 'NewUid' => $iNewUid
+ );
+ }
+ }
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $mResult);
+ }
+
+ public function DoSendMessage() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $oConfig = $this->Config();
+
+ $sDraftFolder = $this->GetActionParam('MessageFolder', '');
+ $sDraftUid = $this->GetActionParam('MessageUid', '');
+ $sSentFolder = $this->GetActionParam('SaveFolder', '');
+ $aDraftInfo = $this->GetActionParam('DraftInfo', null);
+ $bDsn = '1' === (string) $this->GetActionParam('Dsn', '0');
+
+ $oMessage = $this->buildMessage($oAccount, false);
+
+ $this->Plugins()->RunHook('filter.send-message', array($oMessage));
+
+ $mResult = false;
+ try
+ {
+ if ($oMessage)
+ {
+ $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
+
+ $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
+ $oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true);
+
+ if (false !== $iMessageStreamSize)
+ {
+ $this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, $bDsn, true);
+
+ if (\is_array($aDraftInfo) && 3 === \count($aDraftInfo))
+ {
+ $sDraftInfoType = $aDraftInfo[0];
+ $sDraftInfoUid = $aDraftInfo[1];
+ $sDraftInfoFolder = $aDraftInfo[2];
+
+ try
+ {
+ switch (\strtolower($sDraftInfoType))
+ {
+ case 'reply':
+ case 'reply-all':
+ $this->MailClient()->MessageSetFlag($sDraftInfoFolder, array($sDraftInfoUid), true,
+ \MailSo\Imap\Enumerations\MessageFlag::ANSWERED, true);
+ break;
+ case 'forward':
+ $sForwardedFlag = $this->Config()->Get('labs', 'imap_forwarded_flag', '');
+ if (0 < strlen($sForwardedFlag))
+ {
+ $this->MailClient()->MessageSetFlag($sDraftInfoFolder, array($sDraftInfoUid), true,
+ $sForwardedFlag, true);
+ }
+ break;
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
+ }
+ }
+
+ if (0 < \strlen($sSentFolder))
+ {
+ try
+ {
+ if (!$oMessage->GetBcc())
+ {
+ if (\is_resource($rMessageStream))
+ {
+ \rewind($rMessageStream);
+ }
+
+ $this->Plugins()->RunHook('filter.send-message-stream',
+ array($oAccount, &$rMessageStream, &$iMessageStreamSize));
+
+ $this->MailClient()->MessageAppendStream(
+ $rMessageStream, $iMessageStreamSize, $sSentFolder, array(
+ \MailSo\Imap\Enumerations\MessageFlag::SEEN
+ )
+ );
+ }
+ else
+ {
+ $rAppendMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
+
+ $iAppendMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
+ $oMessage->ToStream(false), array($rAppendMessageStream), 8192, true, true, true);
+
+ $this->Plugins()->RunHook('filter.send-message-stream',
+ array($oAccount, &$rAppendMessageStream, &$iAppendMessageStreamSize));
+
+ $this->MailClient()->MessageAppendStream(
+ $rAppendMessageStream, $iAppendMessageStreamSize, $sSentFolder, array(
+ \MailSo\Imap\Enumerations\MessageFlag::SEEN
+ ));
+
+ if (\is_resource($rAppendMessageStream))
+ {
+ fclose($rAppendMessageStream);
+ }
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantSaveMessage, $oException);
+ }
+ }
+
+ if (\is_resource($rMessageStream))
+ {
+ \fclose($rMessageStream);
+ }
+
+ $this->deleteMessageAttachmnets($oAccount);
+
+ if (0 < \strlen($sDraftFolder) && 0 < \strlen($sDraftUid))
+ {
+ try
+ {
+ $this->MailClient()->MessageDelete($sDraftFolder, array($sDraftUid), true, true);
+ }
+ catch (\Throwable $oException)
+ {
+ $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
+ }
+ }
+
+ $mResult = true;
+ }
+ }
+ }
+ catch (Exceptions\ClientException $oException)
+ {
+ throw $oException;
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantSendMessage, $oException);
+ }
+
+ if (false === $mResult)
+ {
+ throw new ClientException(Notifications::CantSendMessage);
+ }
+
+ try
+ {
+ if ($oMessage && $this->AddressBookProvider($oAccount)->IsActive())
+ {
+ $aArrayToFrec = array();
+ $oToCollection = $oMessage->GetTo();
+ if ($oToCollection)
+ {
+ foreach ($oToCollection as /* @var $oEmail \MailSo\Mime\Email */ $oEmail)
+ {
+ $aArrayToFrec[$oEmail->GetEmail(true)] = $oEmail->ToString(false, true);
+ }
+ }
+
+ if (0 < \count($aArrayToFrec))
+ {
+ $oSettings = $this->SettingsProvider()->Load($oAccount);
+
+ $this->AddressBookProvider($oAccount)->IncFrec(
+ $oAccount->ParentEmailHelper(), \array_values($aArrayToFrec),
+ !!$oSettings->GetConf('ContactsAutosave',
+ !!$oConfig->Get('defaults', 'contacts_autosave', true)));
+ }
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ $this->Logger()->WriteException($oException);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoSendReadReceiptMessage() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $oMessage = $this->buildReadReceiptMessage($oAccount);
+
+ $this->Plugins()->RunHook('filter.send-read-receipt-message', array($oMessage, $oAccount));
+
+ $mResult = false;
+ try
+ {
+ if ($oMessage)
+ {
+ $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
+
+ $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
+ $oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true);
+
+ if (false !== $iMessageStreamSize)
+ {
+ $this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, false, false);
+
+ if (\is_resource($rMessageStream))
+ {
+ \fclose($rMessageStream);
+ }
+
+ $mResult = true;
+
+ $sReadReceiptFlag = $this->Config()->Get('labs', 'imap_read_receipt_flag', '');
+ if (!empty($sReadReceiptFlag))
+ {
+ $sFolderFullName = $this->GetActionParam('MessageFolder', '');
+ $sUid = $this->GetActionParam('MessageUid', '');
+
+ $this->Cacher($oAccount)->Set(\RainLoop\KeyPathHelper::ReadReceiptCache($oAccount->Email(), $sFolderFullName, $sUid), '1');
+
+ if (0 < \strlen($sFolderFullName) && 0 < \strlen($sUid))
+ {
+ try
+ {
+ $this->MailClient()->MessageSetFlag($sFolderFullName, array($sUid), true, $sReadReceiptFlag, true, true);
+ }
+ catch (\Throwable $oException) {}
+ }
+ }
+ }
+ }
+ }
+ catch (Exceptions\ClientException $oException)
+ {
+ throw $oException;
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantSendMessage, $oException);
+ }
+
+ if (false === $mResult)
+ {
+ throw new ClientException(Notifications::CantSendMessage);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoMessageSetSeen() : array
+ {
+ return $this->messageSetFlag('MessageSetSeen', __FUNCTION__);
+ }
+
+ public function DoMessageSetSeenToAll() : array
+ {
+ $this->initMailClientConnection();
+
+ $sFolder = $this->GetActionParam('Folder', '');
+ $bSetAction = '1' === (string) $this->GetActionParam('SetAction', '0');
+ $sThreadUids = \trim($this->GetActionParam('ThreadUids', ''));
+
+ try
+ {
+ $this->MailClient()->MessageSetSeenToAll($sFolder, $bSetAction,
+ !empty($sThreadUids) ? explode(',', $sThreadUids) : null);
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::MailServerError, $oException);
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoMessageSetFlagged() : array
+ {
+ return $this->messageSetFlag('MessageSetFlagged', __FUNCTION__);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoMessage() : array
+ {
+ $sRawKey = (string) $this->GetActionParam('RawKey', '');
+
+ $sFolder = '';
+ $iUid = 0;
+
+ $aValues = $this->getDecodedClientRawKeyValue($sRawKey, 4);
+ if ($aValues && 4 === count($aValues))
+ {
+ $sFolder = (string) $aValues[0];
+ $iUid = (int) $aValues[1];
+
+ $this->verifyCacheByKey($sRawKey);
+ }
+ else
+ {
+ $sFolder = $this->GetActionParam('Folder', '');
+ $iUid = (int) $this->GetActionParam('Uid', 0);
+ }
+
+ $oAccount = $this->initMailClientConnection();
+
+ try
+ {
+ $oMessage = $this->MailClient()->Message($sFolder, $iUid, true,
+ $this->cacherForThreads(),
+ (int) $this->Config()->Get('labs', 'imap_body_text_limit', 0)
+ );
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantGetMessage, $oException);
+ }
+
+ if ($oMessage)
+ {
+ $this->Plugins()->RunHook('filter.result-message', array($oMessage));
+
+ $this->cacheByKey($sRawKey);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $oMessage);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoMessageDelete() : array
+ {
+ $this->initMailClientConnection();
+
+ $sFolder = $this->GetActionParam('Folder', '');
+ $aUids = \explode(',', (string) $this->GetActionParam('Uids', ''));
+
+ $aFilteredUids = \array_filter($aUids, function (&$sUid) {
+ $sUid = (int) \trim($sUid);
+ return 0 < $sUid;
+ });
+
+ try
+ {
+ $this->MailClient()->MessageDelete($sFolder, $aFilteredUids, true, true,
+ !!$this->Config()->Get('labs', 'use_imap_expunge_all_on_delete', false));
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantDeleteMessage, $oException);
+ }
+
+ if ($this->Config()->Get('labs', 'use_imap_unselect', true))
+ {
+ try
+ {
+ $this->MailClient()->FolderUnSelect();
+ }
+ catch (\Throwable $oException)
+ {
+ unset($oException);
+ }
+ }
+
+ $sHash = '';
+
+ try
+ {
+ $sHash = $this->MailClient()->FolderHash($sFolder);
+ }
+ catch (\Throwable $oException)
+ {
+ unset($oException);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, '' === $sHash ? false : array($sFolder, $sHash));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoMessageMove() : array
+ {
+ $this->initMailClientConnection();
+
+ $sFromFolder = $this->GetActionParam('FromFolder', '');
+ $sToFolder = $this->GetActionParam('ToFolder', '');
+ $aUids = \explode(',', (string) $this->GetActionParam('Uids', ''));
+ $bMarkAsRead = '1' === (string) $this->GetActionParam('MarkAsRead', '0');
+
+ $aFilteredUids = \array_filter($aUids, function (&$mUid) {
+ $mUid = (int) \trim($mUid);
+ return 0 < $mUid;
+ });
+
+ if ($bMarkAsRead)
+ {
+ try
+ {
+ $this->MailClient()->MessageSetSeen($sFromFolder, $aFilteredUids, true, true);
+ }
+ catch (\Throwable $oException)
+ {
+ unset($oException);
+ }
+ }
+
+ try
+ {
+ $this->MailClient()->MessageMove($sFromFolder, $sToFolder, $aFilteredUids, true,
+ !!$this->Config()->Get('labs', 'use_imap_move', true),
+ !!$this->Config()->Get('labs', 'use_imap_expunge_all_on_delete', false)
+ );
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantMoveMessage, $oException);
+ }
+
+ if ($this->Config()->Get('labs', 'use_imap_unselect', true))
+ {
+ try
+ {
+ $this->MailClient()->FolderUnSelect();
+ }
+ catch (\Throwable $oException)
+ {
+ unset($oException);
+ }
+ }
+
+ $sHash = '';
+
+ try
+ {
+ $sHash = $this->MailClient()->FolderHash($sFromFolder);
+ }
+ catch (\Throwable $oException)
+ {
+ unset($oException);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, '' === $sHash ? false : array($sFromFolder, $sHash));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoMessageCopy() : array
+ {
+ $this->initMailClientConnection();
+
+ $sFromFolder = $this->GetActionParam('FromFolder', '');
+ $sToFolder = $this->GetActionParam('ToFolder', '');
+ $aUids = \explode(',', (string) $this->GetActionParam('Uids', ''));
+
+ $aFilteredUids = \array_filter($aUids, function (&$mUid) {
+ $mUid = (int) \trim($mUid);
+ return 0 < $mUid;
+ });
+
+ try
+ {
+ $this->MailClient()->MessageCopy($sFromFolder, $sToFolder,
+ $aFilteredUids, true);
+
+ $sHash = $this->MailClient()->FolderHash($sFromFolder);
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::CantCopyMessage, $oException);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__,
+ '' === $sHash ? false : array($sFromFolder, $sHash));
+ }
+
+ public function DoMessageUploadAttachments() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ $mResult = false;
+ $self = $this;
+
+ try
+ {
+ $aAttachments = $this->GetActionParam('Attachments', array());
+ if (\is_array($aAttachments) && 0 < \count($aAttachments))
+ {
+ $mResult = array();
+ foreach ($aAttachments as $sAttachment)
+ {
+ if ($aValues = \RainLoop\Utils::DecodeKeyValuesQ($sAttachment))
+ {
+ $sFolder = isset($aValues['Folder']) ? $aValues['Folder'] : '';
+ $iUid = (int) isset($aValues['Uid']) ? $aValues['Uid'] : 0;
+ $sMimeIndex = (string) isset($aValues['MimeIndex']) ? $aValues['MimeIndex'] : '';
+
+ $sTempName = \md5($sAttachment);
+ if (!$this->FilesProvider()->FileExists($oAccount, $sTempName))
+ {
+ $this->MailClient()->MessageMimeStream(
+ function($rResource, $sContentType, $sFileName, $sMimeIndex = '') use ($oAccount, &$mResult, $sTempName, $sAttachment, $self) {
+ if (is_resource($rResource))
+ {
+ $sContentType = (empty($sFileName)) ? 'text/plain' : \MailSo\Base\Utils::MimeContentType($sFileName);
+ $sFileName = $self->MainClearFileName($sFileName, $sContentType, $sMimeIndex);
+
+ if ($self->FilesProvider()->PutFile($oAccount, $sTempName, $rResource))
+ {
+ $mResult[$sTempName] = $sAttachment;
+ }
+ }
+ }, $sFolder, $iUid, true, $sMimeIndex);
+ }
+ else
+ {
+ $mResult[$sTempName] = $sAttachment;
+ }
+ }
+ }
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ throw new ClientException(Notifications::MailServerError, $oException);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $mResult);
+ }
+
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php
new file mode 100644
index 000000000..22c4fc294
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Response.php
@@ -0,0 +1,636 @@
+Plugins()->RunHook('main.default-response-data', array($sActionName, &$mResult));
+ $aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams);
+ $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem));
+ return $aResponseItem;
+ }
+
+ public function TrueResponse(string $sActionName, array $aAdditionalParams = array()) : array
+ {
+ $mResult = true;
+ $this->Plugins()->RunHook('main.default-response-data', array($sActionName, &$mResult));
+ $aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams);
+ $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem));
+ return $aResponseItem;
+ }
+
+ public function FalseResponse(string $sActionName, ?int $iErrorCode = null, ?string $sErrorMessage = null, ?string $sAdditionalErrorMessage = null) : array
+ {
+ $mResult = false;
+ $this->Plugins()
+ ->RunHook('main.default-response-data', array($sActionName, &$mResult))
+ ->RunHook('main.default-response-error-data', array($sActionName, &$iErrorCode, &$sErrorMessage))
+ ;
+
+ $aAdditionalParams = array();
+ if (null !== $iErrorCode)
+ {
+ $aAdditionalParams['ErrorCode'] = (int) $iErrorCode;
+ $aAdditionalParams['ErrorMessage'] = null === $sErrorMessage ? '' : (string) $sErrorMessage;
+ $aAdditionalParams['ErrorMessageAdditional'] = null === $sAdditionalErrorMessage ? '' : (string) $sAdditionalErrorMessage;
+ }
+
+ $aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams);
+
+ $this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem));
+ return $aResponseItem;
+ }
+
+ public function ExceptionResponse(string $sActionName, \Throwable $oException) : array
+ {
+ $iErrorCode = null;
+ $sErrorMessage = null;
+ $sErrorMessageAdditional = null;
+
+ if ($oException instanceof \RainLoop\Exceptions\ClientException)
+ {
+ $iErrorCode = $oException->getCode();
+ $sErrorMessage = null;
+
+ if ($iErrorCode === Notifications::ClientViewError)
+ {
+ $sErrorMessage = $oException->getMessage();
+ }
+
+ $sErrorMessageAdditional = $oException->getAdditionalMessage();
+ if (empty($sErrorMessageAdditional))
+ {
+ $sErrorMessageAdditional = null;
+ }
+ }
+ else
+ {
+ $iErrorCode = Notifications::UnknownError;
+ $sErrorMessage = $oException->getCode().' - '.$oException->getMessage();
+ }
+
+ $oPrevious = $oException->getPrevious();
+ if ($oPrevious)
+ {
+ $this->Logger()->WriteException($oPrevious);
+ }
+ else
+ {
+ $this->Logger()->WriteException($oException);
+ }
+
+ return $this->FalseResponse($sActionName, $iErrorCode, $sErrorMessage, $sErrorMessageAdditional);
+ }
+
+ /**
+ * @param mixed $mResult = false
+ */
+ private function mainDefaultResponse(string $sActionName, $mResult = false, array $aAdditionalParams = array()) : array
+ {
+ $sActionName = 'Do' === \substr($sActionName, 0, 2) ? \substr($sActionName, 2) : $sActionName;
+ $sActionName = \preg_replace('/[^a-zA-Z0-9_]+/', '', $sActionName);
+
+ $aResult = array(
+ 'Action' => $sActionName,
+ 'Result' => $this->responseObject($mResult, $sActionName)
+ );
+
+ foreach ($aAdditionalParams as $sKey => $mValue)
+ {
+ $aResult[$sKey] = $mValue;
+ }
+
+ return $aResult;
+ }
+
+/*
+ $this->Cacher(
+ $this->Config(
+ $this->getAccountFromToken(
+ $this->GetCapa(
+ $this->MailClient(
+ $this->SettingsProvider(
+ $this->Plugins(
+*/
+ private function isFileHasFramedPreview(string $sFileName) : bool
+ {
+ $sExt = \MailSo\Base\Utils::GetFileExtension($sFileName);
+ return \in_array($sExt, array('doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'));
+ }
+
+ private function isFileHasThumbnail(string $sFileName) : bool
+ {
+ static $aCache = array();
+
+ $sExt = \MailSo\Base\Utils::GetFileExtension($sFileName);
+ if (isset($aCache[$sExt]))
+ {
+ return $aCache[$sExt];
+ }
+
+ $bResult = \function_exists('gd_info');
+ if ($bResult)
+ {
+ $bResult = false;
+ switch ($sExt)
+ {
+ case 'png':
+ $bResult = \function_exists('imagecreatefrompng');
+ break;
+ case 'gif':
+ $bResult = \function_exists('imagecreatefromgif');
+ break;
+ case 'jpg':
+ case 'jpeg':
+ $bResult = \function_exists('imagecreatefromjpeg');
+ break;
+ }
+ }
+
+ $aCache[$sExt] = $bResult;
+
+ return $bResult;
+ }
+
+ private function hashFolderFullName(string $sFolderFullName) : string
+ {
+ return \in_array(\strtolower($sFolderFullName), array('inbox', 'sent', 'send', 'drafts',
+ 'spam', 'junk', 'bin', 'trash', 'archive', 'allmail', 'all')) ?
+ $sFolderFullName : \md5($sFolderFullName);
+ }
+
+/*
+ public function RawFramedView() : string
+ {
+ $oAccount = $this->getAccountFromToken(false);
+ if ($oAccount)
+ {
+ $sRawKey = (string) $this->GetActionParam('RawKey', '');
+ $aParams = $this->GetActionParam('Params', null);
+ $this->Http()->ServerNoCache();
+
+ $aData = Utils::DecodeKeyValuesQ($sRawKey);
+ if (isset($aParams[0], $aParams[1], $aParams[2]) &&
+ 'Raw' === $aParams[0] && 'FramedView' === $aParams[2] && isset($aData['Framed']) && $aData['Framed'] && $aData['FileName'])
+ {
+ if ($this->isFileHasFramedPreview($aData['FileName']))
+ {
+ $sNewSpecAuthToken = $this->GetShortLifeSpecAuthToken();
+ if (!empty($sNewSpecAuthToken))
+ {
+ $aParams[1] = '_'.$sNewSpecAuthToken;
+ $aParams[2] = 'View';
+
+ \array_shift($aParams);
+ $sLast = \array_pop($aParams);
+
+ $sUrl = $this->Http()->GetFullUrl().'?/Raw/&q[]=/'.\implode('/', $aParams).'/&q[]=/'.$sLast;
+ $sFullUrl = 'https://docs.google.com/viewer?embedded=true&url='.\urlencode($sUrl);
+
+ \header('Content-Type: text/html; charset=utf-8');
+ echo ''.
+ ''.
+ ''.
+ '';
+ }
+ }
+ }
+ }
+
+
+ return true;
+
+ }
+*/
+
+ private function objectData(object $oData, string $sParent, array $aParameters = array()) : array
+ {
+ $mResult = array();
+ if (\is_object($oData))
+ {
+ $aNames = \explode('\\', \get_class($oData));
+ $mResult = array(
+ '@Object' => \end($aNames)
+ );
+
+ if ($oData instanceof \MailSo\Base\Collection)
+ {
+ $mResult['@Object'] = 'Collection/'.$mResult['@Object'];
+ $mResult['@Count'] = $oData->Count();
+ $mResult['@Collection'] = $this->responseObject($oData->getArrayCopy(), $sParent, $aParameters);
+ }
+ else
+ {
+ $mResult['@Object'] = 'Object/'.$mResult['@Object'];
+ }
+ }
+
+ return $mResult;
+ }
+
+ /**
+ * @param mixed $mResponse
+ *
+ * @return mixed
+ */
+ private $oAccount = null;
+ private $aCheckableFolder = null;
+ private function responseObject($mResponse, string $sParent = '', array $aParameters = array())
+ {
+ /**
+ \MailSo\Mime\Email
+ \RainLoop\Model\Domain
+ \RainLoop\Model\Identity
+ \RainLoop\Model\Template
+ \RainLoop\Providers\AddressBook\Classes\Contact
+ \RainLoop\Providers\AddressBook\Classes\Property
+ \RainLoop\Providers\AddressBook\Classes\Tag
+ \RainLoop\Providers\Filters\Classes\Filter
+ \RainLoop\Providers\Filters\Classes\FilterCondition
+ */
+ if ($mResponse instanceof \JsonSerializable) {
+// return $mResponse->jsonSerialize();
+ return $mResponse;
+ }
+
+ if (\is_object($mResponse))
+ {
+ $sClassName = \get_class($mResponse);
+
+ if ('MailSo\Mail\Message' === $sClassName)
+ {
+ if (null === $this->oAccount) {
+ $this->oAccount = $this->getAccountFromToken(false);
+ }
+ $oAccount = $this->oAccount;
+
+ $iDateTimeStampInUTC = $mResponse->InternalTimeStampInUTC();
+ if (0 === $iDateTimeStampInUTC || !!$this->Config()->Get('labs', 'date_from_headers', false))
+ {
+ $iDateTimeStampInUTC = $mResponse->HeaderTimeStampInUTC();
+ if (0 === $iDateTimeStampInUTC)
+ {
+ $iDateTimeStampInUTC = $mResponse->InternalTimeStampInUTC();
+ }
+ }
+
+ $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
+ 'Folder' => $mResponse->Folder(),
+ 'Uid' => (string) $mResponse->Uid(),
+ 'Subject' => \trim(\MailSo\Base\Utils::Utf8Clear($mResponse->Subject())),
+ 'MessageId' => $mResponse->MessageId(),
+ 'Size' => $mResponse->Size(),
+ 'DateTimeStampInUTC' => $iDateTimeStampInUTC,
+ 'ReplyTo' => $this->responseObject($mResponse->ReplyTo(), $sParent, $aParameters),
+ 'From' => $this->responseObject($mResponse->From(), $sParent, $aParameters),
+ 'To' => $this->responseObject($mResponse->To(), $sParent, $aParameters),
+ 'Cc' => $this->responseObject($mResponse->Cc(), $sParent, $aParameters),
+ 'Bcc' => $this->responseObject($mResponse->Bcc(), $sParent, $aParameters),
+ 'Sender' => $this->responseObject($mResponse->Sender(), $sParent, $aParameters),
+ 'DeliveredTo' => $this->responseObject($mResponse->DeliveredTo(), $sParent, $aParameters),
+ 'Priority' => $mResponse->Priority(),
+ 'Threads' => $mResponse->Threads(),
+ 'Sensitivity' => $mResponse->Sensitivity(),
+ 'UnsubsribeLinks' => $mResponse->UnsubsribeLinks(),
+ 'ExternalProxy' => false,
+ 'ReadReceipt' => ''
+ ));
+
+ $mResult['SubjectParts'] = $this->explodeSubject($mResult['Subject']);
+
+ $oAttachments = $mResponse->Attachments();
+ $iAttachmentsCount = $oAttachments ? $oAttachments->Count() : 0;
+
+ $mResult['HasAttachments'] = 0 < $iAttachmentsCount;
+ $mResult['AttachmentsSpecData'] = $mResult['HasAttachments'] ? $oAttachments->SpecData() : array();
+
+ $sSubject = $mResult['Subject'];
+ $mResult['Hash'] = \md5($mResult['Folder'].$mResult['Uid']);
+ $mResult['RequestHash'] = Utils::EncodeKeyValuesQ(array(
+ 'V' => APP_VERSION,
+ 'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
+ 'Folder' => $mResult['Folder'],
+ 'Uid' => $mResult['Uid'],
+ 'MimeType' => 'message/rfc822',
+ 'FileName' => (0 === \strlen($sSubject) ? 'message-'.$mResult['Uid'] : \MailSo\Base\Utils::ClearXss($sSubject)).'.eml'
+ ));
+
+ // Flags
+ $aFlags = $mResponse->FlagsLowerCase();
+ $mResult['IsSeen'] = \in_array('\\seen', $aFlags);
+ $mResult['IsFlagged'] = \in_array('\\flagged', $aFlags);
+ $mResult['IsAnswered'] = \in_array('\\answered', $aFlags);
+ $mResult['IsDeleted'] = \in_array('\\deleted', $aFlags);
+
+ $sForwardedFlag = $this->Config()->Get('labs', 'imap_forwarded_flag', '');
+ $sReadReceiptFlag = $this->Config()->Get('labs', 'imap_read_receipt_flag', '');
+
+ $mResult['IsForwarded'] = 0 < \strlen($sForwardedFlag) && \in_array(\strtolower($sForwardedFlag), $aFlags);
+ $mResult['IsReadReceipt'] = 0 < \strlen($sReadReceiptFlag) && \in_array(\strtolower($sReadReceiptFlag), $aFlags);
+
+ if (!$this->GetCapa(false, false, Capa::COMPOSER, $oAccount))
+ {
+ $mResult['IsReadReceipt'] = true;
+ }
+
+ $mResult['TextPartIsTrimmed'] = false;
+
+ if ('Message' === $sParent)
+ {
+ $oAttachments = /* @var \MailSo\Mail\AttachmentCollection */ $mResponse->Attachments();
+
+ $bHasExternals = false;
+ $mFoundedCIDs = array();
+ $aContentLocationUrls = array();
+ $mFoundedContentLocationUrls = array();
+
+ if ($oAttachments && 0 < $oAttachments->Count())
+ {
+ foreach ($oAttachments as /* @var \MailSo\Mail\Attachment */ $oAttachment)
+ {
+ if ($oAttachment)
+ {
+ $sContentLocation = $oAttachment->ContentLocation();
+ if ($sContentLocation && 0 < \strlen($sContentLocation))
+ {
+ $aContentLocationUrls[] = $oAttachment->ContentLocation();
+ }
+ }
+ }
+ }
+
+ $sPlain = '';
+ $sHtml = \trim($mResponse->Html());
+
+ if (0 === \strlen($sHtml))
+ {
+ $sPlain = \trim($mResponse->Plain());
+ }
+
+ $mResult['DraftInfo'] = $mResponse->DraftInfo();
+ $mResult['InReplyTo'] = $mResponse->InReplyTo();
+ $mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks();
+ $mResult['References'] = $mResponse->References();
+
+ $fAdditionalExternalFilter = null;
+ if (!!$this->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
+ {
+ $fAdditionalExternalFilter = function ($sUrl) {
+ return './?/ProxyExternal/'.Utils::EncodeKeyValuesQ(array(
+ 'Rnd' => \md5(\microtime(true)),
+ 'Token' => Utils::GetConnectionToken(),
+ 'Url' => $sUrl
+ )).'/';
+ };
+ }
+
+ $sHtml = \preg_replace_callback('/(]*>)([\s\S\r\n\t]*?)(<\/pre>)/mi', function ($aMatches) {
+ return \preg_replace('/[\r\n]+/', '
', $aMatches[1].\trim($aMatches[2]).$aMatches[3]);
+ }, $sHtml);
+
+ $mResult['Html'] = 0 === \strlen($sHtml) ? '' : \MailSo\Base\HtmlUtils::ClearHtml(
+ $sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls, false, false,
+ $fAdditionalExternalFilter, null, !!$this->Config()->Get('labs', 'try_to_detect_hidden_images', false)
+ );
+
+ $mResult['ExternalProxy'] = null !== $fAdditionalExternalFilter;
+
+ $mResult['Plain'] = $sPlain;
+// $mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain);
+
+ $mResult['TextHash'] = \md5($mResult['Html'].$mResult['Plain']);
+
+ $mResult['TextPartIsTrimmed'] = $mResponse->TextPartIsTrimmed();
+
+ $mResult['PgpSigned'] = $mResponse->PgpSigned();
+ $mResult['PgpEncrypted'] = $mResponse->PgpEncrypted();
+ $mResult['PgpSignature'] = $mResponse->PgpSignature();
+
+ unset($sHtml, $sPlain);
+
+ $mResult['HasExternals'] = $bHasExternals;
+ $mResult['HasInternals'] = (\is_array($mFoundedCIDs) && 0 < \count($mFoundedCIDs)) ||
+ (\is_array($mFoundedContentLocationUrls) && 0 < \count($mFoundedContentLocationUrls));
+ $mResult['FoundedCIDs'] = $mFoundedCIDs;
+ $mResult['Attachments'] = $this->responseObject($oAttachments, $sParent, \array_merge($aParameters, array(
+ 'FoundedCIDs' => $mFoundedCIDs,
+ 'FoundedContentLocationUrls' => $mFoundedContentLocationUrls
+ )));
+
+ $mResult['ReadReceipt'] = $mResponse->ReadReceipt();
+ if (0 < \strlen($mResult['ReadReceipt']) && !$mResult['IsReadReceipt'])
+ {
+ if (0 < \strlen($mResult['ReadReceipt']))
+ {
+ try
+ {
+ $oReadReceipt = \MailSo\Mime\Email::Parse($mResult['ReadReceipt']);
+ if (!$oReadReceipt)
+ {
+ $mResult['ReadReceipt'] = '';
+ }
+ }
+ catch (\Throwable $oException) { unset($oException); }
+ }
+
+ if (0 < \strlen($mResult['ReadReceipt']) && '1' === $this->Cacher($oAccount)->Get(
+ \RainLoop\KeyPathHelper::ReadReceiptCache($oAccount->Email(), $mResult['Folder'], $mResult['Uid']), '0'))
+ {
+ $mResult['ReadReceipt'] = '';
+ }
+ }
+ }
+ return $mResult;
+ }
+
+ if ('MailSo\Mail\Attachment' === $sClassName)
+ {
+ if (null === $this->oAccount) {
+ $this->oAccount = $this->getAccountFromToken(false);
+ }
+
+ $mFoundedCIDs = isset($aParameters['FoundedCIDs']) && \is_array($aParameters['FoundedCIDs']) &&
+ 0 < \count($aParameters['FoundedCIDs']) ?
+ $aParameters['FoundedCIDs'] : null;
+
+ $mFoundedContentLocationUrls = isset($aParameters['FoundedContentLocationUrls']) &&
+ \is_array($aParameters['FoundedContentLocationUrls']) &&
+ 0 < \count($aParameters['FoundedContentLocationUrls']) ?
+ $aParameters['FoundedContentLocationUrls'] : null;
+
+ if ($mFoundedCIDs || $mFoundedContentLocationUrls)
+ {
+ $mFoundedCIDs = \array_merge($mFoundedCIDs ? $mFoundedCIDs : array(),
+ $mFoundedContentLocationUrls ? $mFoundedContentLocationUrls : array());
+
+ $mFoundedCIDs = 0 < \count($mFoundedCIDs) ? $mFoundedCIDs : null;
+ }
+
+ $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
+ 'Folder' => $mResponse->Folder(),
+ 'Uid' => (string) $mResponse->Uid(),
+ 'Framed' => false,
+ 'MimeIndex' => (string) $mResponse->MimeIndex(),
+ 'MimeType' => $mResponse->MimeType(),
+ 'FileName' => \MailSo\Base\Utils::ClearFileName(
+ \MailSo\Base\Utils::ClearXss($mResponse->FileName(true))),
+ 'EstimatedSize' => $mResponse->EstimatedSize(),
+ 'CID' => $mResponse->Cid(),
+ 'ContentLocation' => $mResponse->ContentLocation(),
+ 'IsInline' => $mResponse->IsInline(),
+ 'IsThumbnail' => $this->GetCapa(false, false, Capa::ATTACHMENT_THUMBNAILS),
+ 'IsLinked' => ($mFoundedCIDs && \in_array(\trim(\trim($mResponse->Cid()), '<>'), $mFoundedCIDs)) ||
+ ($mFoundedContentLocationUrls && \in_array(\trim($mResponse->ContentLocation()), $mFoundedContentLocationUrls))
+ ));
+
+ $mResult['Framed'] = $this->isFileHasFramedPreview($mResult['FileName']);
+
+ if ($mResult['IsThumbnail'])
+ {
+ $mResult['IsThumbnail'] = $this->isFileHasThumbnail($mResult['FileName']);
+ }
+
+ $mResult['Download'] = Utils::EncodeKeyValuesQ(array(
+ 'V' => APP_VERSION,
+ 'Account' => $this->oAccount ? \md5($this->oAccount->Hash()) : '',
+ 'Folder' => $mResult['Folder'],
+ 'Uid' => $mResult['Uid'],
+ 'MimeIndex' => $mResult['MimeIndex'],
+ 'MimeType' => $mResult['MimeType'],
+ 'FileName' => $mResult['FileName'],
+ 'Framed' => $mResult['Framed']
+ ));
+ return $mResult;
+ }
+
+ if ('MailSo\Mail\Folder' === $sClassName)
+ {
+ $aExtended = null;
+
+// $mStatus = $mResponse->Status();
+// if (\is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT']))
+// {
+// $aExtended = array(
+// 'MessageCount' => (int) $mStatus['MESSAGES'],
+// 'MessageUnseenCount' => (int) $mStatus['UNSEEN'],
+// 'UidNext' => (string) $mStatus['UIDNEXT'],
+// 'Hash' => $this->MailClient()->GenerateFolderHash(
+// $mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'],
+// empty($mStatus['HIGHESTMODSEQ']) ? '' : $mStatus['HIGHESTMODSEQ'])
+// );
+// }
+
+ if (null === $this->aCheckableFolder)
+ {
+ if (null === $this->oAccount) {
+ $this->oAccount = $this->getAccountFromToken(false);
+ }
+ $aCheckable = \json_decode(
+ $this->SettingsProvider(true)
+ ->Load($this->oAccount)
+ ->GetConf('CheckableFolder', '[]')
+ );
+ $this->aCheckableFolder = \is_array($aCheckable) ? $aCheckable : array();
+ }
+
+ return \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
+ 'Name' => $mResponse->Name(),
+ 'FullName' => $mResponse->FullName(),
+ 'FullNameRaw' => $mResponse->FullNameRaw(),
+ 'FullNameHash' => $this->hashFolderFullName($mResponse->FullNameRaw(), $mResponse->FullName()),
+ 'Delimiter' => (string) $mResponse->Delimiter(),
+ 'HasVisibleSubFolders' => $mResponse->HasVisibleSubFolders(),
+ 'IsSubscribed' => $mResponse->IsSubscribed(),
+ 'IsExists' => $mResponse->IsExists(),
+ 'IsSelectable' => $mResponse->IsSelectable(),
+ 'Flags' => $mResponse->FlagsLowerCase(),
+ 'Checkable' => \in_array($mResponse->FullNameRaw(), $this->aCheckableFolder),
+ 'Extended' => $aExtended,
+ 'SubFolders' => $this->responseObject($mResponse->SubFolders(), $sParent, $aParameters)
+ ));
+ }
+
+ if ('MailSo\Mail\MessageCollection' === $sClassName)
+ {
+ return \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
+ 'MessageCount' => $mResponse->MessageCount,
+ 'MessageUnseenCount' => $mResponse->MessageUnseenCount,
+ 'MessageResultCount' => $mResponse->MessageResultCount,
+ 'Folder' => $mResponse->FolderName,
+ 'FolderHash' => $mResponse->FolderHash,
+ 'UidNext' => $mResponse->UidNext,
+ 'ThreadUid' => $mResponse->ThreadUid,
+ 'NewMessages' => $this->responseObject($mResponse->NewMessages),
+ 'Filtered' => $mResponse->Filtered,
+ 'Offset' => $mResponse->Offset,
+ 'Limit' => $mResponse->Limit,
+ 'Search' => $mResponse->Search
+ ));
+ }
+
+ if ('MailSo\Mail\AttachmentCollection' === $sClassName)
+ {
+ return \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
+ 'InlineCount' => $mResponse->InlineCount()
+ ));
+ }
+
+ if ('MailSo\Mail\FolderCollection' === $sClassName)
+ {
+ return \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
+ 'Namespace' => $mResponse->GetNamespace(),
+ 'FoldersHash' => isset($mResponse->FoldersHash) ? $mResponse->FoldersHash : '',
+ 'IsThreadsSupported' => $mResponse->IsThreadsSupported,
+ 'Optimized' => $mResponse->Optimized,
+ 'CountRec' => $mResponse->CountRec(),
+ 'SystemFolders' => isset($mResponse->SystemFolders) && \is_array($mResponse->SystemFolders) ?
+ $mResponse->SystemFolders : array()
+ ));
+ }
+
+ if ('MailSo\Mime\EmailCollection' === $sClassName)
+ {
+ $mResult = array();
+ if (100 < \count($mResponse)) {
+ $mResponse = $mResponse->Slice(0, 100);
+ }
+ foreach ($mResponse as $iKey => $oItem) {
+ $mResult[$iKey] = $this->responseObject($oItem, $sParent, $aParameters);
+ }
+ return $mResult;
+ }
+
+ if ($mResponse instanceof \MailSo\Base\Collection)
+ {
+ $mResult = array();
+ foreach ($mResponse as $iKey => $oItem) {
+ $mResult[$iKey] = $this->responseObject($oItem, $sParent, $aParameters);
+ }
+ return $mResult;
+ }
+
+ return '["'.$sClassName.'"]';
+ }
+
+ if (\is_array($mResponse))
+ {
+ foreach ($mResponse as $iKey => $oItem)
+ {
+ $mResponse[$iKey] = $this->responseObject($oItem, $sParent, $aParameters);
+ }
+
+ return $mResponse;
+ }
+
+ return $mResponse;
+ }
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Templates.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Templates.php
new file mode 100644
index 000000000..158372a62
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Templates.php
@@ -0,0 +1,133 @@
+getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $oTemplate = new \RainLoop\Model\Template();
+ if (!$oTemplate->FromJSON($this->GetActionParams(), true))
+ {
+ throw new ClientException(Notifications::InvalidInputArgument);
+ }
+
+ if ('' === $oTemplate->Id())
+ {
+ $oTemplate->GenerateID();
+ }
+
+ $aTemplatesForSave = array();
+ $aTemplates = $this->GetTemplates($oAccount);
+
+
+ foreach ($aTemplates as $oItem)
+ {
+ if ($oItem && $oItem->Id() !== $oTemplate->Id())
+ {
+ $aTemplatesForSave[] = $oItem;
+ }
+ }
+
+ $aTemplatesForSave[] = $oTemplate;
+
+ return $this->DefaultResponse(__FUNCTION__, $this->SetTemplates($oAccount, $aTemplatesForSave));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoTemplateDelete() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sId = \trim($this->GetActionParam('IdToDelete', ''));
+ if (empty($sId))
+ {
+ throw new ClientException(Notifications::UnknownError);
+ }
+
+ $aNew = array();
+ $aTemplates = $this->GetTemplates($oAccount);
+ foreach ($aTemplates as $oItem)
+ {
+ if ($oItem && $sId !== $oItem->Id())
+ {
+ $aNew[] = $oItem;
+ }
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $this->SetTemplates($oAccount, $aNew));
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoTemplateGetByID() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sId = \trim($this->GetActionParam('ID', ''));
+ if (empty($sId))
+ {
+ throw new ClientException(Notifications::UnknownError);
+ }
+
+ $oTemplate = false;
+ $aTemplates = $this->GetTemplates($oAccount);
+
+ foreach ($aTemplates as $oItem)
+ {
+ if ($oItem && $sId === $oItem->Id())
+ {
+ $oTemplate = $oItem;
+ break;
+ }
+ }
+
+ $oTemplate->SetPopulateAlways(true);
+ return $this->DefaultResponse(__FUNCTION__, $oTemplate);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoTemplates() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Capa::TEMPLATES, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, array(
+ 'Templates' => $this->GetTemplates($oAccount)
+ ));
+ }
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/TwoFactor.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/TwoFactor.php
new file mode 100644
index 000000000..adfbe8df9
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/TwoFactor.php
@@ -0,0 +1,151 @@
+getAccountFromToken();
+
+ if (!$this->TwoFactorAuthProvider()->IsActive() ||
+ !$this->GetCapa(false, false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__,
+ $this->getTwoFactorInfo($oAccount, true));
+ }
+
+ public function DoCreateTwoFactorSecret() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->TwoFactorAuthProvider()->IsActive() ||
+ !$this->GetCapa(false, false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sEmail = $oAccount->ParentEmailHelper();
+
+ $sSecret = $this->TwoFactorAuthProvider()->CreateSecret();
+
+ $aCodes = array();
+ for ($iIndex = 9; $iIndex > 0; $iIndex--)
+ {
+ $aCodes[] = \rand(100000000, 900000000);
+ }
+
+ $this->StorageProvider()->Put($oAccount,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
+ 'two_factor',
+ \RainLoop\Utils::EncodeKeyValues(array(
+ 'User' => $sEmail,
+ 'Enable' => false,
+ 'Secret' => $sSecret,
+ 'BackupCodes' => \implode(' ', $aCodes)
+ ))
+ );
+
+ $this->requestSleep();
+
+ return $this->DefaultResponse(__FUNCTION__,
+ $this->getTwoFactorInfo($oAccount));
+ }
+
+ public function DoShowTwoFactorSecret() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->TwoFactorAuthProvider()->IsActive() ||
+ !$this->GetCapa(false, false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $aResult = $this->getTwoFactorInfo($oAccount);
+ unset($aResult['BackupCodes']);
+
+ return $this->DefaultResponse(__FUNCTION__, $aResult);
+ }
+
+ public function DoEnableTwoFactor() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->TwoFactorAuthProvider()->IsActive() ||
+ !$this->GetCapa(false, false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sEmail = $oAccount->ParentEmailHelper();
+
+ $bResult = false;
+ $mData = $this->getTwoFactorInfo($oAccount);
+ if (isset($mData['Secret'], $mData['BackupCodes']))
+ {
+ $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')),
+ 'Secret' => $mData['Secret'],
+ 'BackupCodes' => $mData['BackupCodes']
+ ))
+ );
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $bResult);
+ }
+
+ public function DoTestTwoFactorInfo() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->TwoFactorAuthProvider()->IsActive() ||
+ !$this->GetCapa(false, false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $sCode = \trim($this->GetActionParam('Code', ''));
+
+ $aData = $this->getTwoFactorInfo($oAccount);
+ $sSecret = !empty($aData['Secret']) ? $aData['Secret'] : '';
+
+// $this->Logger()->WriteDump(array(
+// $sCode, $sSecret, $aData,
+// $this->TwoFactorAuthProvider()->VerifyCode($sSecret, $sCode)
+// ));
+
+ $this->requestSleep();
+
+ return $this->DefaultResponse(__FUNCTION__,
+ $this->TwoFactorAuthProvider()->VerifyCode($sSecret, $sCode));
+ }
+
+ public function DoClearTwoFactorInfo() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->TwoFactorAuthProvider()->IsActive() ||
+ !$this->GetCapa(false, false, \RainLoop\Enumerations\Capa::TWO_FACTOR, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $this->StorageProvider()->Clear($oAccount,
+ \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
+ 'two_factor'
+ );
+
+ return $this->DefaultResponse(__FUNCTION__,
+ $this->getTwoFactorInfo($oAccount, true));
+ }
+
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php
new file mode 100644
index 000000000..3df9f4405
--- /dev/null
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php
@@ -0,0 +1,513 @@
+GetActionParam('Email', ''));
+ $sPassword = $this->GetActionParam('Password', '');
+ $sLanguage = $this->GetActionParam('Language', '');
+ $bSignMe = '1' === (string) $this->GetActionParam('SignMe', '0');
+
+ $sAdditionalCode = $this->GetActionParam('AdditionalCode', '');
+ $bAdditionalCodeSignMe = '1' === (string) $this->GetActionParam('AdditionalCodeSignMe', '0');
+
+ $oAccount = null;
+
+ $this->Logger()->AddSecret($sPassword);
+
+ if ('sleep@sleep.dev' === $sEmail && 0 < \strlen($sPassword) &&
+ \is_numeric($sPassword) && $this->Config()->Get('debug', 'enable', false) &&
+ 0 < (int) $sPassword && 30 > (int) $sPassword
+ )
+ {
+ \sleep((int) $sPassword);
+ throw new Exceptions\ClientException(Notifications::AuthError);
+ }
+
+ try
+ {
+ $oAccount = $this->LoginProcess($sEmail, $sPassword,
+ $bSignMe ? $this->generateSignMeToken($sEmail) : '',
+ $sAdditionalCode, $bAdditionalCodeSignMe);
+ }
+ catch (Exceptions\ClientException $oException)
+ {
+ if ($oException &&
+ Notifications::AccountTwoFactorAuthRequired === $oException->getCode())
+ {
+ return $this->DefaultResponse(__FUNCTION__, true, array(
+ 'TwoFactorAuth' => true
+ ));
+ }
+ else
+ {
+ throw $oException;
+ }
+ }
+
+ $this->AuthToken($oAccount);
+
+ if ($oAccount && 0 < \strlen($sLanguage))
+ {
+ $oSettings = $this->SettingsProvider()->Load($oAccount);
+ if ($oSettings)
+ {
+ $sLanguage = $this->ValidateLanguage($sLanguage);
+ $sCurrentLanguage = $oSettings->GetConf('Language', '');
+
+ if ($sCurrentLanguage !== $sLanguage)
+ {
+ $oSettings->SetConf('Language', $sLanguage);
+ $this->SettingsProvider()->Save($oAccount, $oSettings);
+ }
+ }
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ /**
+ * @throws \MailSo\Base\Exceptions\Exception
+ */
+ public function DoAttachmentsActions() : array
+ {
+ if (!$this->GetCapa(false, false, Enumerations\Capa::ATTACHMENTS_ACTIONS))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $oAccount = $this->initMailClientConnection();
+
+ $sAction = $this->GetActionParam('Do', '');
+ $aHashes = $this->GetActionParam('Hashes', null);
+
+ $mResult = false;
+ $bError = false;
+ $aData = false;
+
+ if (\is_array($aHashes) && 0 < \count($aHashes))
+ {
+ $aData = array();
+ foreach ($aHashes as $sZipHash)
+ {
+ $aResult = $this->getMimeFileByHash($oAccount, $sZipHash);
+ if (!empty($aResult['FileHash']))
+ {
+ $aData[] = $aResult;
+ }
+ else
+ {
+ $bError = true;
+ break;
+ }
+ }
+ }
+
+ $oFilesProvider = $this->FilesProvider();
+ if (!empty($sAction) && !$bError && \is_array($aData) && 0 < \count($aData) &&
+ $oFilesProvider && $oFilesProvider->IsActive())
+ {
+ $bError = false;
+ switch (\strtolower($sAction))
+ {
+ case 'zip':
+
+ if (\class_exists('ZipArchive'))
+ {
+ $sZipHash = \MailSo\Base\Utils::Md5Rand();
+ $sZipFileName = $oFilesProvider->GenerateLocalFullFileName($oAccount, $sZipHash);
+
+ if (!empty($sZipFileName))
+ {
+ $oZip = new \ZipArchive();
+ $oZip->open($sZipFileName, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE);
+ $oZip->setArchiveComment('SnappyMail/'.APP_VERSION);
+
+ foreach ($aData as $aItem)
+ {
+ $sFileName = (string) (isset($aItem['FileName']) ? $aItem['FileName'] : 'file.dat');
+ $sFileHash = (string) (isset($aItem['FileHash']) ? $aItem['FileHash'] : '');
+
+ if (!empty($sFileHash))
+ {
+ $sFullFileNameHash = $oFilesProvider->GetFileName($oAccount, $sFileHash);
+ if (!$oZip->addFile($sFullFileNameHash, $sFileName))
+ {
+ $bError = true;
+ }
+ }
+ }
+
+ if (!$bError)
+ {
+ $bError = !$oZip->close();
+ }
+ else
+ {
+ $oZip->close();
+ }
+ }
+
+ foreach ($aData as $aItem)
+ {
+ $sFileHash = (string) (isset($aItem['FileHash']) ? $aItem['FileHash'] : '');
+ if (!empty($sFileHash))
+ {
+ $oFilesProvider->Clear($oAccount, $sFileHash);
+ }
+ }
+
+ if (!$bError)
+ {
+ $mResult = array(
+ 'Files' => array(array(
+ 'FileName' => 'attachments.zip',
+ 'Hash' => Utils::EncodeKeyValuesQ(array(
+ 'V' => APP_VERSION,
+ 'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
+ 'FileName' => 'attachments.zip',
+ 'MimeType' => 'application/zip',
+ 'FileHash' => $sZipHash
+ ))
+ ))
+ );
+ }
+ }
+ break;
+ }
+ }
+ else
+ {
+ $bError = true;
+ }
+
+ $this->requestSleep();
+ return $this->DefaultResponse(__FUNCTION__, $bError ? false : $mResult);
+ }
+
+ public function DoLogout() : array
+ {
+ $oAccount = $this->getAccountFromToken(false);
+ if ($oAccount)
+ {
+ if ($oAccount->SignMe())
+ {
+ $this->ClearSignMeData($oAccount);
+ }
+
+ if (!$oAccount->IsAdditionalAccount())
+ {
+ Utils::ClearCookie(Actions::AUTH_SPEC_TOKEN_KEY);
+ }
+ }
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoAppDelayStart() : array
+ {
+ $this->Plugins()->RunHook('service.app-delay-start-begin');
+
+ Utils::UpdateConnectionToken();
+
+ $bMainCache = false;
+ $bFilesCache = false;
+ $bVersionsCache = false;
+
+ $iOneDay1 = 60 * 60 * 23;
+ $iOneDay2 = 60 * 60 * 25;
+ $iOneDay3 = 60 * 60 * 30;
+
+ $sTimers = $this->StorageProvider()->Get(null,
+ Providers\Storage\Enumerations\StorageType::NOBODY, 'Cache/Timers', '');
+
+ $aTimers = \explode(',', $sTimers);
+
+ $iMainCacheTime = !empty($aTimers[0]) && \is_numeric($aTimers[0]) ? (int) $aTimers[0] : 0;
+ $iFilesCacheTime = !empty($aTimers[1]) && \is_numeric($aTimers[1]) ? (int) $aTimers[1] : 0;
+ $iVersionsCacheTime = !empty($aTimers[2]) && \is_numeric($aTimers[2]) ? (int) $aTimers[2] : 0;
+
+ if (0 === $iMainCacheTime || $iMainCacheTime + $iOneDay1 < \time())
+ {
+ $bMainCache = true;
+ $iMainCacheTime = \time();
+ }
+
+ if (0 === $iFilesCacheTime || $iFilesCacheTime + $iOneDay2 < \time())
+ {
+ $bFilesCache = true;
+ $iFilesCacheTime = \time();
+ }
+
+ if (0 === $iVersionsCacheTime || $iVersionsCacheTime + $iOneDay3 < \time())
+ {
+ $bVersionsCache = true;
+ $iVersionsCacheTime = \time();
+ }
+
+ if ($bMainCache || $bFilesCache || $bVersionsCache)
+ {
+ if (!$this->StorageProvider()->Put(null,
+ Providers\Storage\Enumerations\StorageType::NOBODY, 'Cache/Timers',
+ \implode(',', array($iMainCacheTime, $iFilesCacheTime, $iVersionsCacheTime))))
+ {
+ $bMainCache = $bFilesCache = $bVersionsCache = false;
+ }
+ }
+
+ if ($bMainCache)
+ {
+ $this->Logger()->Write('Cacher GC: Begin');
+ $this->Cacher()->GC(48);
+ $this->Logger()->Write('Cacher GC: End');
+ }
+ else if ($bFilesCache)
+ {
+ $this->Logger()->Write('Files GC: Begin');
+ $this->FilesProvider()->GC(48);
+ $this->Logger()->Write('Files GC: End');
+ }
+
+ $this->Plugins()->RunHook('service.app-delay-start-end');
+
+ return $this->TrueResponse(__FUNCTION__);
+ }
+
+ public function DoSettingsUpdate() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+ if (!$this->GetCapa(false, false, Enumerations\Capa::SETTINGS, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $self = $this;
+ $oConfig = $this->Config();
+
+ $oSettings = $this->SettingsProvider()->Load($oAccount);
+ $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
+
+ if ($oConfig->Get('webmail', 'allow_languages_on_settings', true))
+ {
+ $this->setSettingsFromParams($oSettings, 'Language', 'string', function ($sLanguage) use ($self) {
+ return $self->ValidateLanguage($sLanguage);
+ });
+ }
+ else
+ {
+ $oSettings->SetConf('Language', $this->ValidateLanguage($oConfig->Get('webmail', 'language', 'en')));
+ }
+
+ if ($this->GetCapa(false, false, Enumerations\Capa::THEMES, $oAccount))
+ {
+ $this->setSettingsFromParams($oSettingsLocal, 'Theme', 'string', function ($sTheme) use ($self) {
+ return $self->ValidateTheme($sTheme);
+ });
+ }
+ else
+ {
+ $oSettingsLocal->SetConf('Theme', $this->ValidateTheme($oConfig->Get('webmail', 'theme', 'Default')));
+ }
+
+ $this->setSettingsFromParams($oSettings, 'MPP', 'int', function ($iValue) {
+ return (int) (\in_array($iValue, array(10, 20, 30, 50, 100, 150, 200, 300)) ? $iValue : 20);
+ });
+
+ $this->setSettingsFromParams($oSettings, 'Layout', 'int', function ($iValue) {
+ return (int) (\in_array((int) $iValue, array(Enumerations\Layout::NO_PREVIW,
+ Enumerations\Layout::SIDE_PREVIEW, Enumerations\Layout::BOTTOM_PREVIEW)) ?
+ $iValue : Enumerations\Layout::SIDE_PREVIEW);
+ });
+
+ $this->setSettingsFromParams($oSettings, 'EditorDefaultType', 'string');
+ $this->setSettingsFromParams($oSettings, 'ShowImages', 'bool');
+ $this->setSettingsFromParams($oSettings, 'ContactsAutosave', 'bool');
+ $this->setSettingsFromParams($oSettings, 'DesktopNotifications', 'bool');
+ $this->setSettingsFromParams($oSettings, 'SoundNotification', 'bool');
+ $this->setSettingsFromParams($oSettings, 'UseCheckboxesInList', 'bool');
+ $this->setSettingsFromParams($oSettings, 'AllowDraftAutosave', 'bool');
+ $this->setSettingsFromParams($oSettings, 'AutoLogout', 'int');
+
+ $this->setSettingsFromParams($oSettings, 'EnableTwoFactor', 'bool');
+
+ $this->setSettingsFromParams($oSettingsLocal, 'UseThreads', 'bool');
+ $this->setSettingsFromParams($oSettingsLocal, 'ReplySameFolder', 'bool');
+
+ return $this->DefaultResponse(__FUNCTION__,
+ $this->SettingsProvider()->Save($oAccount, $oSettings) &&
+ $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
+ }
+
+ public function DoQuota() : array
+ {
+ $oAccount = $this->initMailClientConnection();
+
+ if (!$this->GetCapa(false, false, Enumerations\Capa::QUOTA, $oAccount))
+ {
+ return $this->DefaultResponse(__FUNCTION__, array(0, 0, 0, 0));
+ }
+
+ try
+ {
+ $aQuota = $this->MailClient()->Quota();
+ }
+ catch (\Throwable $oException)
+ {
+ throw new Exceptions\ClientException(Notifications::MailServerError, $oException);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $aQuota);
+ }
+
+ public function DoSuggestions() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $sQuery = \trim($this->GetActionParam('Query', ''));
+ $iLimit = (int) $this->Config()->Get('contacts', 'suggestions_limit', 20);
+
+ $aResult = array();
+
+ $this->Plugins()->RunHook('ajax.suggestions-input-parameters', array(&$sQuery, &$iLimit, $oAccount));
+
+ $iLimit = (int) $iLimit;
+ if (5 > $iLimit)
+ {
+ $iLimit = 5;
+ }
+
+ $this->Plugins()->RunHook('ajax.suggestions-pre', array(&$aResult, $sQuery, $oAccount, $iLimit));
+
+ if ($iLimit > \count($aResult) && 0 < \strlen($sQuery))
+ {
+ try
+ {
+ // Address Book
+ $oAddressBookProvider = $this->AddressBookProvider($oAccount);
+ if ($oAddressBookProvider && $oAddressBookProvider->IsActive())
+ {
+ $aSuggestions = $oAddressBookProvider->GetSuggestions($oAccount->ParentEmailHelper(), $sQuery, $iLimit);
+ if (0 === \count($aResult))
+ {
+ $aResult = $aSuggestions;
+ }
+ else
+ {
+ $aResult = \array_merge($aResult, $aSuggestions);
+ }
+ }
+ }
+ catch (\Throwable $oException)
+ {
+ $this->Logger()->WriteException($oException);
+ }
+ }
+
+ if ($iLimit > \count($aResult) && 0 < \strlen($sQuery))
+ {
+ $oSuggestionsProvider = $this->SuggestionsProvider();
+ if ($oSuggestionsProvider && $oSuggestionsProvider->IsActive())
+ {
+ $aSuggestionsProviderResult = $oSuggestionsProvider->Process($oAccount, $sQuery, $iLimit);
+ if (\is_array($aSuggestionsProviderResult) && 0 < \count($aSuggestionsProviderResult))
+ {
+ $aResult = \array_merge($aResult, $aSuggestionsProviderResult);
+ }
+ }
+
+ }
+
+ $aResult = Utils::RemoveSuggestionDuplicates($aResult);
+ if ($iLimit < \count($aResult))
+ {
+ $aResult = \array_slice($aResult, 0, $iLimit);
+ }
+
+ $this->Plugins()->RunHook('ajax.suggestions-post', array(&$aResult, $sQuery, $oAccount, $iLimit));
+
+ $aResult = Utils::RemoveSuggestionDuplicates($aResult);
+ if ($iLimit < \count($aResult))
+ {
+ $aResult = \array_slice($aResult, 0, $iLimit);
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $aResult);
+ }
+
+ public function DoComposeUploadExternals() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ $mResult = false;
+ $aExternals = $this->GetActionParam('Externals', array());
+ if (\is_array($aExternals) && 0 < \count($aExternals))
+ {
+ $oHttp = \MailSo\Base\Http::SingletonInstance();
+
+ $mResult = array();
+ foreach ($aExternals as $sUrl)
+ {
+ $mResult[$sUrl] = '';
+
+ $sTempName = \md5($sUrl);
+
+ $iCode = 0;
+ $sContentType = '';
+
+ $rFile = $this->FilesProvider()->GetFile($oAccount, $sTempName, 'wb+');
+ if ($rFile && $oHttp->SaveUrlToFile($sUrl, $rFile, '', $sContentType, $iCode, $this->Logger(), 60,
+ $this->Config()->Get('labs', 'curl_proxy', ''), $this->Config()->Get('labs', 'curl_proxy_auth', '')))
+ {
+ $mResult[$sUrl] = $sTempName;
+ }
+
+ if (\is_resource($rFile))
+ {
+ \fclose($rFile);
+ }
+ }
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $mResult);
+ }
+
+ public function DoClearUserBackground() : array
+ {
+ $oAccount = $this->getAccountFromToken();
+
+ if (!$this->GetCapa(false, false, Enumerations\Capa::USER_BACKGROUND, $oAccount))
+ {
+ return $this->FalseResponse(__FUNCTION__);
+ }
+
+ $oSettings = $this->SettingsProvider()->Load($oAccount);
+ if ($oAccount && $oSettings)
+ {
+ $this->StorageProvider()->Clear($oAccount,
+ Providers\Storage\Enumerations\StorageType::CONFIG,
+ 'background'
+ );
+
+ $oSettings->SetConf('UserBackgroundName', '');
+ $oSettings->SetConf('UserBackgroundHash', '');
+ }
+
+ return $this->DefaultResponse(__FUNCTION__, $oAccount && $oSettings ?
+ $this->SettingsProvider()->Save($oAccount, $oSettings) : false);
+ }
+
+}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Domain.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Domain.php
index 5cb635245..2cf460a42 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Domain.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Domain.php
@@ -4,7 +4,7 @@ namespace RainLoop\Model;
use MailSo\Net\Enumerations\ConnectionSecurityType;
-class Domain
+class Domain implements \JsonSerializable
{
const DEFAULT_FORWARDED_FLAG = '$Forwarded';
@@ -401,20 +401,45 @@ class Domain
return true;
}
- public function ToSimpleJSON(bool $bAjax = false) : array
+ public function ToSimpleJSON() : array
{
return array(
- 'Name' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->Name()) : $this->Name(),
- 'IncHost' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->IncHost()) : $this->IncHost(),
+ 'Name' => $this->Name(),
+ 'IncHost' => $this->IncHost(),
'IncPort' => $this->IncPort(),
'IncSecure' => $this->IncSecure(),
'IncShortLogin' => $this->IncShortLogin(),
'UseSieve' => $this->UseSieve(),
- 'SieveHost' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->SieveHost()) : $this->SieveHost(),
+ 'SieveHost' => $this->SieveHost(),
'SievePort' => $this->SievePort(),
'SieveSecure' => $this->SieveSecure(),
'SieveAllowRaw' => $this->SieveAllowRaw(),
- 'OutHost' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->OutHost()) : $this->OutHost(),
+ 'OutHost' => $this->OutHost(),
+ 'OutPort' => $this->OutPort(),
+ 'OutSecure' => $this->OutSecure(),
+ 'OutShortLogin' => $this->OutShortLogin(),
+ 'OutAuth' => $this->OutAuth(),
+ 'OutUsePhpMail' => $this->OutUsePhpMail(),
+ 'WhiteList' => $this->WhiteList(),
+ 'AliasName' => $this->AliasName()
+ );
+ }
+
+ public function jsonSerialize()
+ {
+ return array(
+// '@Object' => 'Object/Domain',
+ 'Name' => \MailSo\Base\Utils::IdnToUtf8($this->Name()),
+ 'IncHost' => \MailSo\Base\Utils::IdnToUtf8($this->IncHost()),
+ 'IncPort' => $this->IncPort(),
+ 'IncSecure' => $this->IncSecure(),
+ 'IncShortLogin' => $this->IncShortLogin(),
+ 'UseSieve' => $this->UseSieve(),
+ 'SieveHost' => \MailSo\Base\Utils::IdnToUtf8($this->SieveHost()),
+ 'SievePort' => $this->SievePort(),
+ 'SieveSecure' => $this->SieveSecure(),
+ 'SieveAllowRaw' => $this->SieveAllowRaw(),
+ 'OutHost' => \MailSo\Base\Utils::IdnToUtf8($this->OutHost()),
'OutPort' => $this->OutPort(),
'OutSecure' => $this->OutSecure(),
'OutShortLogin' => $this->OutShortLogin(),
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php
index 9dda1c114..54023f46b 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Identity.php
@@ -2,7 +2,7 @@
namespace RainLoop\Model;
-class Identity
+class Identity implements \JsonSerializable
{
/**
* @var string
@@ -111,11 +111,25 @@ class Identity
return false;
}
- public function ToSimpleJSON(bool $bAjax = false) : array
+ public function ToSimpleJSON() : array
{
return array(
'Id' => $this->Id(),
- 'Email' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->Email()) : $this->Email(),
+ 'Email' => $this->Email(),
+ 'Name' => $this->Name(),
+ 'ReplyTo' => $this->ReplyTo(),
+ 'Bcc' => $this->Bcc(),
+ 'Signature' => $this->Signature(),
+ 'SignatureInsertBefore' => $this->SignatureInsertBefore()
+ );
+ }
+
+ public function jsonSerialize()
+ {
+ return array(
+// '@Object' => 'Object/Identity',
+ 'Id' => $this->Id(),
+ 'Email' => \MailSo\Base\Utils::IdnToUtf8($this->Email()),
'Name' => $this->Name(),
'ReplyTo' => $this->ReplyTo(),
'Bcc' => $this->Bcc(),
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Template.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Template.php
index c710a44bb..951225431 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Template.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Template.php
@@ -2,7 +2,7 @@
namespace RainLoop\Model;
-class Template
+class Template implements \JsonSerializable
{
/**
* @var string
@@ -66,32 +66,32 @@ class Template
return false;
}
- public function ToSimpleJSON(bool $bAjax = false) : array
+ public function ToSimpleJSON() : array
+ {
+ return array(
+ 'ID' => $this->Id(),
+ 'Name' => $this->Name(),
+ 'Body' => $this->Body()
+ );
+ }
+
+ public function jsonSerialize()
{
$sBody = $this->Body();
$bPopulated = true;
-
- if ($bAjax && $bPopulated && !$this->bPopulateAlways)
- {
- if (1024 * 5 < \strlen($sBody) || true)
- {
+ if ($bPopulated && !$this->bPopulateAlways) {
+ if (1024 * 5 < \strlen($sBody) || true) {
$bPopulated = false;
$sBody = '';
}
}
-
- $aResult = array(
+ return array(
+// '@Object' => 'Object/Template',
'ID' => $this->Id(),
'Name' => $this->Name(),
- 'Body' => $sBody
+ 'Body' => $sBody,
+ 'Populated' => $bPopulated
);
-
- if ($bAjax)
- {
- $aResult['Populated'] = $bPopulated;
- }
-
- return $aResult;
}
public function GenerateID() : bool
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php
index 7a355f5ec..75117998c 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Contact.php
@@ -7,7 +7,7 @@ use
RainLoop\Providers\AddressBook\Classes\Property
;
-class Contact
+class Contact implements \JsonSerializable
{
/**
* @var string
@@ -636,4 +636,19 @@ class Contact
return true;
}
+
+ public function jsonSerialize()
+ {
+ $properties = array();
+ foreach ($this->Properties as $property) {
+ $properties[] = $property->jsonSerialize();
+ }
+ return array(
+ '@Object' => 'Object/Contact',
+ 'display' => \MailSo\Base\Utils::Utf8Clear($this->Display),
+ 'readOnly' => $this->ReadOnly,
+ 'IdPropertyFromSearch' => $this->IdPropertyFromSearch,
+ 'properties' => $properties
+ );
+ }
}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php
index 4b26c4bb9..316421c82 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Property.php
@@ -4,7 +4,7 @@ namespace RainLoop\Providers\AddressBook\Classes;
use RainLoop\Providers\AddressBook\Enumerations\PropertyType;
-class Property
+class Property implements \JsonSerializable
{
/**
* @var int
@@ -145,4 +145,20 @@ class Property
}
}
}
+
+ public function jsonSerialize()
+ {
+ // Simple hack
+ if ($this && $this->IsWeb())
+ {
+ $this->Value = \preg_replace('/(skype|ftp|http[s]?)\\\:\/\//i', '$1://', $this->Value);
+ }
+ return array(
+ '@Object' => 'Object/Property',
+ 'IdProperty' => $this->IdProperty,
+ 'Type' => $this->Type,
+ 'TypeStr' => $this->TypeStr,
+ 'Value' => \MailSo\Base\Utils::Utf8Clear($this->Value)
+ ));
+ }
}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Tag.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Tag.php
index 83c2b7cc1..c5973a680 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Tag.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/Classes/Tag.php
@@ -2,7 +2,7 @@
namespace RainLoop\Providers\AddressBook\Classes;
-class Tag
+class Tag implements \JsonSerializable
{
/**
* @var string
@@ -30,4 +30,14 @@ class Tag
$this->Name = '';
$this->ReadOnly = false;
}
+
+ public function jsonSerialize()
+ {
+ return array(
+ '@Object' => 'Object/Tag',
+ 'id' => $this->IdContactTag,
+ 'name' => \MailSo\Base\Utils::Utf8Clear($mResponse->Name),
+ 'readOnly' => $this->ReadOnly
+ );
+ }
}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php
index b4b8a9344..0e70d480b 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/Filter.php
@@ -2,7 +2,7 @@
namespace RainLoop\Providers\Filters\Classes;
-class Filter
+class Filter implements \JsonSerializable
{
/**
* @var string
@@ -166,11 +166,6 @@ class Filter
return $this->bKeep;
}
- public function serializeToJson() : string
- {
- return \json_encode($this->ToSimpleJSON());
- }
-
public function unserializeFromJson(string $sFilterJson)
{
$aFilterJson = \json_decode(\trim($sFilterJson), true);
@@ -210,22 +205,14 @@ class Filter
return true;
}
- public function ToSimpleJSON(bool $bAjax = false) : array
+ public function jsonSerialize()
{
- $aConditions = array();
- foreach ($this->Conditions() as $oItem)
- {
- if ($oItem)
- {
- $aConditions[] = $oItem->ToSimpleJSON($bAjax);
- }
- }
-
return array(
+ '@Object' => 'Object/Filter',
'ID' => $this->ID(),
'Enabled' => $this->Enabled(),
'Name' => $this->Name(),
- 'Conditions' => $aConditions,
+ 'Conditions' => $this->Conditions(),
'ConditionsType' => $this->ConditionsType(),
'ActionType' => $this->ActionType(),
'ActionValue' => $this->ActionValue(),
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php
index 3f7623253..396d4f913 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/Classes/FilterCondition.php
@@ -2,7 +2,7 @@
namespace RainLoop\Providers\Filters\Classes;
-class FilterCondition
+class FilterCondition implements \JsonSerializable
{
/**
* @var string
@@ -71,16 +71,6 @@ class FilterCondition
return true;
}
- public function ToSimpleJSON(bool $bAjax = false) : array
- {
- return array(
- 'Field' => $this->Field(),
- 'Type' => $this->Type(),
- 'Value' => $this->Value(),
- 'ValueSecond' => $this->ValueSecond()
- );
- }
-
public static function CollectionFromJSON(array $aCollection) : array
{
$aResult = array();
@@ -97,4 +87,15 @@ class FilterCondition
}
return $aResult;
}
+
+ public function jsonSerialize()
+ {
+ return array(
+// '@Object' => 'Object/FilterCondition',
+ 'Field' => $this->Field(),
+ 'Type' => $this->Type(),
+ 'Value' => $this->Value(),
+ 'ValueSecond' => $this->ValueSecond()
+ );
+ }
}
diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php
index 7836f13af..45877fdd5 100644
--- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php
+++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Filters/SieveStorage.php
@@ -472,7 +472,7 @@ class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface
$aData[] = '/*';
$aData[] = 'BEGIN:FILTER:'.$oItem->ID();
$aData[] = 'BEGIN:HEADER';
- $aData[] = \chunk_split(\base64_encode($oItem->serializeToJson()), 74, $sNL).'END:HEADER';
+ $aData[] = \chunk_split(\base64_encode(\json_encode($oItem)), 74, $sNL).'END:HEADER';
$aData[] = '*/';
$aData[] = $oItem->Enabled() ? '' : '/* @Filter is disabled ';
$aData[] = $this->filterToSieveScript($oItem, $aCapa);