Cleanup Action reponse handling and use typed properties

This commit is contained in:
the-djmaze 2022-12-21 14:12:35 +01:00
parent 31b1096f4d
commit 219b155ede
20 changed files with 395 additions and 662 deletions

View file

@ -918,13 +918,12 @@ class Actions
public function DoPing(): array public function DoPing(): array
{ {
return $this->DefaultResponse(__FUNCTION__, 'Pong'); return $this->DefaultResponse('Pong');
} }
public function DoVersion(): array public function DoVersion(): array
{ {
return $this->DefaultResponse(__FUNCTION__, return $this->DefaultResponse(APP_VERSION === (string)$this->GetActionParam('Version', ''));
APP_VERSION === (string)$this->GetActionParam('Version', ''));
} }
public function MainClearFileName(string $sFileName, string $sContentType, string $sMimeIndex, int $iMaxLength = 250): string public function MainClearFileName(string $sFileName, string $sContentType, string $sMimeIndex, int $iMaxLength = 250): string
@ -1028,7 +1027,7 @@ class Actions
} }
} }
return $this->DefaultResponse(__FUNCTION__, $aResponse); return $this->DefaultResponse($aResponse);
} }
public function Capa(bool $bAdmin, ?Model\Account $oAccount = null): array public function Capa(bool $bAdmin, ?Model\Account $oAccount = null): array

View file

@ -15,10 +15,7 @@ use RainLoop\Utils;
trait Accounts trait Accounts
{ {
/** private ?\RainLoop\Providers\Identities $oIdentitiesProvider = null;
* @var RainLoop\Providers\Identities
*/
private $oIdentitiesProvider;
protected function GetMainEmail(Account $oAccount) protected function GetMainEmail(Account $oAccount)
{ {
@ -78,7 +75,7 @@ trait Accounts
$oMainAccount = $this->getMainAccountFromToken(); $oMainAccount = $this->getMainAccountFromToken();
if (!$this->GetCapa(Capa::ADDITIONAL_ACCOUNTS)) { if (!$this->GetCapa(Capa::ADDITIONAL_ACCOUNTS)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$aAccounts = $this->GetAccounts($oMainAccount); $aAccounts = $this->GetAccounts($oMainAccount);
@ -107,7 +104,7 @@ trait Accounts
$this->SetAccounts($oMainAccount, $aAccounts); $this->SetAccounts($oMainAccount, $aAccounts);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
protected function loadAdditionalAccountImapClient(string $sEmail): \MailSo\Imap\ImapClient protected function loadAdditionalAccountImapClient(string $sEmail): \MailSo\Imap\ImapClient
@ -137,7 +134,7 @@ trait Accounts
{ {
$oImapClient = $this->loadAdditionalAccountImapClient($this->GetActionParam('email', '')); $oImapClient = $this->loadAdditionalAccountImapClient($this->GetActionParam('email', ''));
$oInfo = $oImapClient->FolderStatus('INBOX'); $oInfo = $oImapClient->FolderStatus('INBOX');
return $this->DefaultResponse(__FUNCTION__, [ return $this->DefaultResponse([
'unreadEmails' => \max(0, $oInfo->UNSEEN) 'unreadEmails' => \max(0, $oInfo->UNSEEN)
]); ]);
} }
@ -172,7 +169,7 @@ trait Accounts
$oMainAccount = $this->getMainAccountFromToken(); $oMainAccount = $this->getMainAccountFromToken();
if (!$this->GetCapa(Capa::ADDITIONAL_ACCOUNTS)) { if (!$this->GetCapa(Capa::ADDITIONAL_ACCOUNTS)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$sEmailToDelete = \trim($this->GetActionParam('EmailToDelete', '')); $sEmailToDelete = \trim($this->GetActionParam('EmailToDelete', ''));
@ -191,10 +188,10 @@ trait Accounts
unset($aAccounts[$sEmailToDelete]); unset($aAccounts[$sEmailToDelete]);
$this->SetAccounts($oMainAccount, $aAccounts); $this->SetAccounts($oMainAccount, $aAccounts);
return $this->TrueResponse(__FUNCTION__, array('Reload' => $bReload)); return $this->TrueResponse(array('Reload' => $bReload));
} }
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
/** /**
@ -227,9 +224,9 @@ trait Accounts
} }
// $this->Plugins()->InitAppData($bAdmin, $aResult, $oAccount); // $this->Plugins()->InitAppData($bAdmin, $aResult, $oAccount);
return $this->DefaultResponse(__FUNCTION__, $aResult); return $this->DefaultResponse($aResult);
} }
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
/** /**
@ -245,7 +242,7 @@ trait Accounts
} }
$this->IdentitiesProvider()->UpdateIdentity($oAccount, $oIdentity); $this->IdentitiesProvider()->UpdateIdentity($oAccount, $oIdentity);
return $this->DefaultResponse(__FUNCTION__, true); return $this->TrueResponse();
} }
/** /**
@ -256,7 +253,7 @@ trait Accounts
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(Capa::IDENTITIES)) { if (!$this->GetCapa(Capa::IDENTITIES)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$sId = \trim($this->GetActionParam('IdToDelete', '')); $sId = \trim($this->GetActionParam('IdToDelete', ''));
@ -265,7 +262,7 @@ trait Accounts
} }
$this->IdentitiesProvider()->DeleteIdentity($oAccount, $sId); $this->IdentitiesProvider()->DeleteIdentity($oAccount, $sId);
return $this->DefaultResponse(__FUNCTION__, true); return $this->TrueResponse();
} }
/** /**
@ -277,7 +274,7 @@ trait Accounts
$aIdentities = $this->GetActionParam('Identities', null); $aIdentities = $this->GetActionParam('Identities', null);
if (!\is_array($aAccounts) && !\is_array($aIdentities)) { if (!\is_array($aAccounts) && !\is_array($aIdentities)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
if (\is_array($aAccounts) && 1 < \count($aAccounts)) { if (\is_array($aAccounts) && 1 < \count($aAccounts)) {
@ -289,7 +286,7 @@ trait Accounts
$this->SetAccounts($oAccount, $aAccounts); $this->SetAccounts($oAccount, $aAccounts);
} }
return $this->DefaultResponse(__FUNCTION__, $this->LocalStorageProvider()->Put( return $this->DefaultResponse($this->LocalStorageProvider()->Put(
$this->getAccountFromToken(), $this->getAccountFromToken(),
StorageType::CONFIG, StorageType::CONFIG,
'identities_order', 'identities_order',
@ -305,7 +302,7 @@ trait Accounts
public function DoAccountsAndIdentities(): array public function DoAccountsAndIdentities(): array
{ {
// https://github.com/the-djmaze/snappymail/issues/571 // https://github.com/the-djmaze/snappymail/issues/571
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'Accounts' => \array_values(\array_map(function($value){ 'Accounts' => \array_values(\array_map(function($value){
return [ return [
'email' => \MailSo\Base\Utils::IdnToUtf8($value['email'] ?? $value[1]), 'email' => \MailSo\Base\Utils::IdnToUtf8($value['email'] ?? $value[1]),

View file

@ -11,7 +11,7 @@ use RainLoop\Utils;
trait Admin trait Admin
{ {
protected static $AUTH_ADMIN_TOKEN_KEY = 'smadmin'; protected static string $AUTH_ADMIN_TOKEN_KEY = 'smadmin';
public function IsAdminLoggined(bool $bThrowExceptionOnFalse = true) : bool public function IsAdminLoggined(bool $bThrowExceptionOnFalse = true) : bool
{ {
@ -22,8 +22,7 @@ trait Admin
} }
} }
if ($bThrowExceptionOnFalse) if ($bThrowExceptionOnFalse) {
{
throw new ClientException(Notifications::AuthError); throw new ClientException(Notifications::AuthError);
} }

View file

@ -17,7 +17,7 @@ trait Attachments
$aHashes = $this->GetActionParam('Hashes', null); $aHashes = $this->GetActionParam('Hashes', null);
$oFilesProvider = $this->FilesProvider(); $oFilesProvider = $this->FilesProvider();
if (empty($sAction) || !$this->GetCapa(Capa::ATTACHMENTS_ACTIONS) || !$oFilesProvider || !$oFilesProvider->IsActive()) { if (empty($sAction) || !$this->GetCapa(Capa::ATTACHMENTS_ACTIONS) || !$oFilesProvider || !$oFilesProvider->IsActive()) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$oAccount = $this->initMailClientConnection(); $oAccount = $this->initMailClientConnection();
@ -42,7 +42,7 @@ trait Attachments
$mUIDs = 1 < \count($mUIDs); $mUIDs = 1 < \count($mUIDs);
if ($bError || !\count($aData)) { if ($bError || !\count($aData)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$mResult = false; $mResult = false;
@ -130,7 +130,7 @@ trait Attachments
} }
// $this->requestSleep(); // $this->requestSleep();
return $this->DefaultResponse(__FUNCTION__, $bError ? false : $mResult); return $this->DefaultResponse($bError ? false : $mResult);
} }
private function getMimeFileByHash(\RainLoop\Model\Account $oAccount, string $sHash) : array private function getMimeFileByHash(\RainLoop\Model\Account $oAccount, string $sHash) : array

View file

@ -10,9 +10,8 @@ trait Contacts
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
$oAddressBookProvider = $this->AddressBookProvider($oAccount); $oAddressBookProvider = $this->AddressBookProvider($oAccount);
if (!$oAddressBookProvider || !$oAddressBookProvider->IsActive()) if (!$oAddressBookProvider || !$oAddressBookProvider->IsActive()) {
{ return $this->FalseResponse();
return $this->FalseResponse(__FUNCTION__);
} }
$sPassword = $this->GetActionParam('Password', ''); $sPassword = $this->GetActionParam('Password', '');
@ -28,7 +27,7 @@ trait Contacts
'Url' => $this->GetActionParam('Url', '') 'Url' => $this->GetActionParam('Url', '')
)); ));
return $this->DefaultResponse(__FUNCTION__, $bResult); return $this->DefaultResponse($bResult);
} }
public function DoContactsSync() : array public function DoContactsSync() : array
@ -44,7 +43,7 @@ trait Contacts
if (!$oAddressBookProvider->Sync()) { if (!$oAddressBookProvider->Sync()) {
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ContactsSyncError, null, 'AddressBookProvider->Sync() failed'); throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::ContactsSyncError, null, 'AddressBookProvider->Sync() failed');
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoContacts() : array public function DoContacts() : array
@ -61,13 +60,12 @@ trait Contacts
$mResult = array(); $mResult = array();
$oAbp = $this->AddressBookProvider($oAccount); $oAbp = $this->AddressBookProvider($oAccount);
if ($oAbp->IsActive()) if ($oAbp->IsActive()) {
{
$iResultCount = 0; $iResultCount = 0;
$mResult = $oAbp->GetContacts($iOffset, $iLimit, $sSearch, $iResultCount); $mResult = $oAbp->GetContacts($iOffset, $iLimit, $sSearch, $iResultCount);
} }
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'Offset' => $iOffset, 'Offset' => $iOffset,
'Limit' => $iLimit, 'Limit' => $iLimit,
'Count' => $iResultCount, 'Count' => $iResultCount,
@ -84,12 +82,11 @@ trait Contacts
$aFilteredUids = \array_filter(\array_map('intval', $aUids)); $aFilteredUids = \array_filter(\array_map('intval', $aUids));
$bResult = false; $bResult = false;
if (\count($aFilteredUids) && $this->AddressBookProvider($oAccount)->IsActive()) if (\count($aFilteredUids) && $this->AddressBookProvider($oAccount)->IsActive()) {
{
$bResult = $this->AddressBookProvider($oAccount)->DeleteContacts($aFilteredUids); $bResult = $this->AddressBookProvider($oAccount)->DeleteContacts($aFilteredUids);
} }
return $this->DefaultResponse(__FUNCTION__, $bResult); return $this->DefaultResponse($bResult);
} }
public function DoContactSave() : array public function DoContactSave() : array
@ -116,7 +113,7 @@ trait Contacts
} }
} }
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'ResultID' => $bResult ? $oContact->id : '', 'ResultID' => $bResult ? $oContact->id : '',
'Result' => $bResult 'Result' => $bResult
)); ));
@ -131,38 +128,28 @@ trait Contacts
$aFile = $this->GetActionParam('File', null); $aFile = $this->GetActionParam('File', null);
$iError = $this->GetActionParam('Error', \RainLoop\Enumerations\UploadError::UNKNOWN); $iError = $this->GetActionParam('Error', \RainLoop\Enumerations\UploadError::UNKNOWN);
if ($oAccount && UPLOAD_ERR_OK === $iError && \is_array($aFile)) if ($oAccount && UPLOAD_ERR_OK === $iError && \is_array($aFile)) {
{
$sSavedName = 'upload-post-'.\md5($aFile['name'].$aFile['tmp_name']); $sSavedName = 'upload-post-'.\md5($aFile['name'].$aFile['tmp_name']);
if (!$this->FilesProvider()->MoveUploadedFile($oAccount, $sSavedName, $aFile['tmp_name'])) if (!$this->FilesProvider()->MoveUploadedFile($oAccount, $sSavedName, $aFile['tmp_name'])) {
{
$iError = \RainLoop\Enumerations\UploadError::ON_SAVING; $iError = \RainLoop\Enumerations\UploadError::ON_SAVING;
} } else {
else
{
\ini_set('auto_detect_line_endings', true); \ini_set('auto_detect_line_endings', true);
$mData = $this->FilesProvider()->GetFile($oAccount, $sSavedName); $mData = $this->FilesProvider()->GetFile($oAccount, $sSavedName);
if ($mData) if ($mData) {
{
$sFileStart = \fread($mData, 20); $sFileStart = \fread($mData, 20);
\rewind($mData); \rewind($mData);
if (false !== $sFileStart) if (false !== $sFileStart) {
{
$sFileStart = \trim($sFileStart); $sFileStart = \trim($sFileStart);
if (false !== \strpos($sFileStart, 'BEGIN:VCARD')) if (false !== \strpos($sFileStart, 'BEGIN:VCARD')) {
{
$mResponse = $this->importContactsFromVcfFile($oAccount, $mData); $mResponse = $this->importContactsFromVcfFile($oAccount, $mData);
} } else if (false !== \strpos($sFileStart, ',') || false !== \strpos($sFileStart, ';')) {
else if (false !== \strpos($sFileStart, ',') || false !== \strpos($sFileStart, ';'))
{
$mResponse = $this->importContactsFromCsvFile($oAccount, $mData, $sFileStart); $mResponse = $this->importContactsFromCsvFile($oAccount, $mData, $sFileStart);
} }
} }
} }
if (\is_resource($mData)) if (\is_resource($mData)) {
{
\fclose($mData); \fclose($mData);
} }
@ -173,18 +160,15 @@ trait Contacts
} }
} }
if (UPLOAD_ERR_OK !== $iError) if (UPLOAD_ERR_OK !== $iError) {
{
$iClientError = \RainLoop\Enumerations\UploadError::NORMAL; $iClientError = \RainLoop\Enumerations\UploadError::NORMAL;
$sError = $this->getUploadErrorMessageByCode($iError, $iClientError); $sError = $this->getUploadErrorMessageByCode($iError, $iClientError);
if (!empty($sError)) {
if (!empty($sError)) return $this->FalseResponse($iClientError, $sError);
{
return $this->FalseResponse(__FUNCTION__, $iClientError, $sError);
} }
} }
return $this->DefaultResponse(__FUNCTION__, $mResponse); return $this->DefaultResponse($mResponse);
} }
public function setContactsSyncData(\RainLoop\Model\Account $oAccount, array $aData) : bool public function setContactsSyncData(\RainLoop\Model\Account $oAccount, array $aData) : bool

View file

@ -6,10 +6,7 @@ use RainLoop\Enumerations\Capa;
trait Filters trait Filters
{ {
/** private ?\RainLoop\Providers\Filters $oFiltersProvider = null;
* @var \RainLoop\Providers\Filters
*/
private $oFiltersProvider;
/** /**
* @throws \MailSo\RuntimeException * @throws \MailSo\RuntimeException
@ -18,12 +15,11 @@ trait Filters
{ {
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(Capa::SIEVE, $oAccount)) if (!$this->GetCapa(Capa::SIEVE, $oAccount)) {
{ return $this->FalseResponse();
return $this->FalseResponse(__FUNCTION__);
} }
return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->Load($oAccount)); return $this->DefaultResponse($this->FiltersProvider()->Load($oAccount));
} }
/** /**
@ -34,7 +30,7 @@ trait Filters
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(Capa::SIEVE, $oAccount)) { if (!$this->GetCapa(Capa::SIEVE, $oAccount)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$sName = $this->GetActionParam('name', ''); $sName = $this->GetActionParam('name', '');
@ -43,7 +39,7 @@ trait Filters
// $this->FiltersProvider()->ActivateScript($oAccount, $sName); // $this->FiltersProvider()->ActivateScript($oAccount, $sName);
} }
return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->Save( return $this->DefaultResponse($this->FiltersProvider()->Save(
$oAccount, $sName, $this->GetActionParam('body', '') $oAccount, $sName, $this->GetActionParam('body', '')
)); ));
} }
@ -56,10 +52,10 @@ trait Filters
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(Capa::SIEVE, $oAccount)) { if (!$this->GetCapa(Capa::SIEVE, $oAccount)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->ActivateScript( return $this->DefaultResponse($this->FiltersProvider()->ActivateScript(
$oAccount, $this->GetActionParam('name', '') $oAccount, $this->GetActionParam('name', '')
)); ));
} }
@ -72,10 +68,10 @@ trait Filters
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(Capa::SIEVE, $oAccount)) { if (!$this->GetCapa(Capa::SIEVE, $oAccount)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
return $this->DefaultResponse(__FUNCTION__, $this->FiltersProvider()->DeleteScript( return $this->DefaultResponse($this->FiltersProvider()->DeleteScript(
$oAccount, $this->GetActionParam('name', '') $oAccount, $this->GetActionParam('name', '')
)); ));
} }

View file

@ -38,7 +38,7 @@ trait Folders
} }
} }
return $this->DefaultResponse(__FUNCTION__, true); return $this->TrueResponse();
} }
public function DoFolders() : array public function DoFolders() : array
@ -79,7 +79,7 @@ trait Folders
); );
} }
return $this->DefaultResponse(__FUNCTION__, $oFolderCollection); return $this->DefaultResponse($oFolderCollection);
} }
public function DoFolderCreate() : array public function DoFolderCreate() : array
@ -95,7 +95,7 @@ trait Folders
); );
// FolderInformation(string $sFolderName, int $iPrevUidNext = 0, array $aUids = array()) // FolderInformation(string $sFolderName, int $iPrevUidNext = 0, array $aUids = array())
return $this->DefaultResponse(__FUNCTION__, $oFolder); return $this->DefaultResponse($oFolder);
} }
catch (\Throwable $oException) catch (\Throwable $oException)
{ {
@ -113,7 +113,7 @@ trait Folders
$sMetadataKey => $this->GetActionParam('Value') ?: null $sMetadataKey => $this->GetActionParam('Value') ?: null
]); ]);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoFolderSubscribe() : array public function DoFolderSubscribe() : array
@ -135,7 +135,7 @@ trait Folders
); );
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoFolderCheckable() : array public function DoFolderCheckable() : array
@ -143,18 +143,16 @@ trait Folders
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
$sFolderFullName = $this->GetActionParam('Folder', ''); $sFolderFullName = $this->GetActionParam('Folder', '');
$bCheckable = '1' === (string) $this->GetActionParam('Checkable', '0');
$oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount); $oSettingsLocal = $this->SettingsProvider(true)->Load($oAccount);
$sCheckableFolder = $oSettingsLocal->GetConf('CheckableFolder', '[]'); $aCheckableFolder = \json_decode($oSettingsLocal->GetConf('CheckableFolder', '[]'));
$aCheckableFolder = \json_decode($sCheckableFolder);
if (!\is_array($aCheckableFolder)) { if (!\is_array($aCheckableFolder)) {
$aCheckableFolder = array(); $aCheckableFolder = array();
} }
if ($bCheckable) { if (!empty($this->GetActionParam('Checkable', '0'))) {
$aCheckableFolder[] = $sFolderFullName; $aCheckableFolder[] = $sFolderFullName;
} else { } else {
$aCheckableFolderNew = array(); $aCheckableFolderNew = array();
@ -170,8 +168,7 @@ trait Folders
$oSettingsLocal->SetConf('CheckableFolder', \json_encode($aCheckableFolder)); $oSettingsLocal->SetConf('CheckableFolder', \json_encode($aCheckableFolder));
return $this->DefaultResponse(__FUNCTION__, return $this->DefaultResponse($this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
$this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
} }
/** /**
@ -194,7 +191,7 @@ trait Folders
throw new ClientException(Notifications::CantRenameFolder, $oException); throw new ClientException(Notifications::CantRenameFolder, $oException);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
/** /**
@ -219,7 +216,7 @@ trait Folders
} }
// FolderInformation(string $sFolderName, int $iPrevUidNext = 0, array $aUids = array()) // FolderInformation(string $sFolderName, int $iPrevUidNext = 0, array $aUids = array())
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'Name' => $sName, 'Name' => $sName,
'FullName' => $sFullName, 'FullName' => $sFullName,
)); ));
@ -245,7 +242,7 @@ trait Folders
throw new ClientException(Notifications::CantDeleteFolder, $oException); throw new ClientException(Notifications::CantDeleteFolder, $oException);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
/** /**
@ -264,7 +261,7 @@ trait Folders
throw new ClientException(Notifications::MailServerError, $oException); throw new ClientException(Notifications::MailServerError, $oException);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
/** /**
@ -276,12 +273,11 @@ trait Folders
try try
{ {
$aInboxInformation = $this->MailClient()->FolderInformation( return $this->DefaultResponse($this->MailClient()->FolderInformation(
$this->GetActionParam('Folder', ''), $this->GetActionParam('Folder', ''),
(int) $this->GetActionParam('UidNext', 0), (int) $this->GetActionParam('UidNext', 0),
new \MailSo\Imap\SequenceSet($this->GetActionParam('FlagsUids', [])) new \MailSo\Imap\SequenceSet($this->GetActionParam('FlagsUids', []))
); ));
return $this->DefaultResponse(__FUNCTION__, $aInboxInformation);
} }
catch (\Throwable $oException) catch (\Throwable $oException)
{ {
@ -323,7 +319,7 @@ trait Folders
} }
} }
return $this->DefaultResponse(__FUNCTION__, $aResult); return $this->DefaultResponse($aResult);
} }
public function DoSystemFoldersUpdate() : array public function DoSystemFoldersUpdate() : array
@ -338,7 +334,6 @@ trait Folders
$oSettingsLocal->SetConf('TrashFolder', $this->GetActionParam('Trash', '')); $oSettingsLocal->SetConf('TrashFolder', $this->GetActionParam('Trash', ''));
$oSettingsLocal->SetConf('ArchiveFolder', $this->GetActionParam('Archive', '')); $oSettingsLocal->SetConf('ArchiveFolder', $this->GetActionParam('Archive', ''));
return $this->DefaultResponse(__FUNCTION__, return $this->DefaultResponse($this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
$this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
} }
} }

View file

@ -25,8 +25,7 @@ trait Messages
$sRawKey = $this->GetActionParam('RawKey', ''); $sRawKey = $this->GetActionParam('RawKey', '');
$aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey), true); $aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey), true);
if ($aValues && 6 < \count($aValues)) if ($aValues && 6 < \count($aValues)) {
{
$this->verifyCacheByKey($sRawKey); $this->verifyCacheByKey($sRawKey);
// $oParams->sHash = (string) $aValues['Hash']; // $oParams->sHash = (string) $aValues['Hash'];
@ -42,9 +41,7 @@ trait Messages
if ($oParams->bUseThreads && isset($aValues['ThreadUid'])) { if ($oParams->bUseThreads && isset($aValues['ThreadUid'])) {
$oParams->iThreadUid = $aValues['ThreadUid']; $oParams->iThreadUid = $aValues['ThreadUid'];
} }
} } else {
else
{
$oParams->sFolderName = $this->GetActionParam('Folder', ''); $oParams->sFolderName = $this->GetActionParam('Folder', '');
$oParams->iOffset = $this->GetActionParam('Offset', 0); $oParams->iOffset = $this->GetActionParam('Offset', 0);
$oParams->iLimit = $this->GetActionParam('Limit', 10); $oParams->iLimit = $this->GetActionParam('Limit', 10);
@ -57,8 +54,7 @@ trait Messages
} }
} }
if (!\strlen($oParams->sFolderName)) if (!\strlen($oParams->sFolderName)) {
{
throw new ClientException(Notifications::CantGetMessageList); throw new ClientException(Notifications::CantGetMessageList);
} }
@ -85,12 +81,11 @@ trait Messages
throw new ClientException(Notifications::CantGetMessageList, $oException); throw new ClientException(Notifications::CantGetMessageList, $oException);
} }
if ($oMessageList) if ($oMessageList) {
{
$this->cacheByKey($sRawKey); $this->cacheByKey($sRawKey);
} }
return $this->DefaultResponse(__FUNCTION__, $oMessageList); return $this->DefaultResponse($oMessageList);
} }
public function DoSaveMessage() : array public function DoSaveMessage() : array
@ -98,8 +93,7 @@ trait Messages
$oAccount = $this->initMailClientConnection(); $oAccount = $this->initMailClientConnection();
$sDraftFolder = $this->GetActionParam('SaveFolder', ''); $sDraftFolder = $this->GetActionParam('SaveFolder', '');
if (!\strlen($sDraftFolder)) if (!\strlen($sDraftFolder)) {
{
throw new ClientException(Notifications::UnknownError); throw new ClientException(Notifications::UnknownError);
} }
@ -108,15 +102,13 @@ trait Messages
$this->Plugins()->RunHook('filter.save-message', array($oMessage)); $this->Plugins()->RunHook('filter.save-message', array($oMessage));
$mResult = false; $mResult = false;
if ($oMessage) if ($oMessage) {
{
$rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
$iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
$oMessage->ToStream(false), array($rMessageStream), 8192, true, true); $oMessage->ToStream(false), array($rMessageStream), 8192, true, true);
if (false !== $iMessageStreamSize) if (false !== $iMessageStreamSize) {
{
$sMessageId = $oMessage->MessageId(); $sMessageId = $oMessage->MessageId();
\rewind($rMessageStream); \rewind($rMessageStream);
@ -126,8 +118,7 @@ trait Messages
$rMessageStream, $iMessageStreamSize, $sDraftFolder, array(MessageFlag::SEEN), $iNewUid $rMessageStream, $iMessageStreamSize, $sDraftFolder, array(MessageFlag::SEEN), $iNewUid
); );
if (!empty($sMessageId) && (null === $iNewUid || 0 === $iNewUid)) if (!empty($sMessageId) && (null === $iNewUid || 0 === $iNewUid)) {
{
$iNewUid = $this->MailClient()->FindMessageUidByMessageId($sDraftFolder, $sMessageId); $iNewUid = $this->MailClient()->FindMessageUidByMessageId($sDraftFolder, $sMessageId);
} }
@ -135,13 +126,11 @@ trait Messages
$sMessageFolder = $this->GetActionParam('MessageFolder', ''); $sMessageFolder = $this->GetActionParam('MessageFolder', '');
$iMessageUid = (int) $this->GetActionParam('MessageUid', 0); $iMessageUid = (int) $this->GetActionParam('MessageUid', 0);
if (\strlen($sMessageFolder) && 0 < $iMessageUid) if (\strlen($sMessageFolder) && 0 < $iMessageUid) {
{
$this->MailClient()->MessageDelete($sMessageFolder, new SequenceSet($iMessageUid)); $this->MailClient()->MessageDelete($sMessageFolder, new SequenceSet($iMessageUid));
} }
if (null !== $iNewUid && 0 < $iNewUid) if (null !== $iNewUid && 0 < $iNewUid) {
{
$mResult = array( $mResult = array(
'NewFolder' => $sDraftFolder, 'NewFolder' => $sDraftFolder,
'NewUid' => $iNewUid 'NewUid' => $iNewUid
@ -150,7 +139,7 @@ trait Messages
} }
} }
return $this->DefaultResponse(__FUNCTION__, $mResult); return $this->DefaultResponse($mResult);
} }
public function DoSendMessage() : array public function DoSendMessage() : array
@ -169,20 +158,17 @@ trait Messages
$mResult = false; $mResult = false;
try try
{ {
if ($oMessage) if ($oMessage) {
{
$rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
$iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
$oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true); $oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true);
if (false !== $iMessageStreamSize) if (false !== $iMessageStreamSize) {
{
$bDsn = !empty($this->GetActionParam('Dsn', 0)); $bDsn = !empty($this->GetActionParam('Dsn', 0));
$this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, $bDsn, true); $this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, $bDsn, true);
if (\is_array($aDraftInfo) && 3 === \count($aDraftInfo)) if (\is_array($aDraftInfo) && 3 === \count($aDraftInfo)) {
{
$sDraftInfoType = $aDraftInfo[0]; $sDraftInfoType = $aDraftInfo[0];
$iDraftInfoUid = (int) $aDraftInfo[1]; $iDraftInfoUid = (int) $aDraftInfo[1];
$sDraftInfoFolder = $aDraftInfo[2]; $sDraftInfoFolder = $aDraftInfo[2];
@ -206,14 +192,11 @@ trait Messages
} }
} }
if (\strlen($sSentFolder)) if (\strlen($sSentFolder)) {
{
try try
{ {
if (!$oMessage->GetBcc()) if (!$oMessage->GetBcc()) {
{ if (\is_resource($rMessageStream)) {
if (\is_resource($rMessageStream))
{
\rewind($rMessageStream); \rewind($rMessageStream);
} }
@ -223,9 +206,7 @@ trait Messages
$this->MailClient()->MessageAppendStream( $this->MailClient()->MessageAppendStream(
$rMessageStream, $iMessageStreamSize, $sSentFolder, array(MessageFlag::SEEN) $rMessageStream, $iMessageStreamSize, $sSentFolder, array(MessageFlag::SEEN)
); );
} } else {
else
{
$rAppendMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); $rAppendMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
$iAppendMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( $iAppendMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
@ -238,8 +219,7 @@ trait Messages
$rAppendMessageStream, $iAppendMessageStreamSize, $sSentFolder, array(MessageFlag::SEEN) $rAppendMessageStream, $iAppendMessageStreamSize, $sSentFolder, array(MessageFlag::SEEN)
); );
if (\is_resource($rAppendMessageStream)) if (\is_resource($rAppendMessageStream)) {
{
fclose($rAppendMessageStream); fclose($rAppendMessageStream);
} }
} }
@ -250,8 +230,7 @@ trait Messages
} }
} }
if (\is_resource($rMessageStream)) if (\is_resource($rMessageStream)) {
{
\fclose($rMessageStream); \fclose($rMessageStream);
} }
@ -259,8 +238,7 @@ trait Messages
$sDraftFolder = $this->GetActionParam('MessageFolder', ''); $sDraftFolder = $this->GetActionParam('MessageFolder', '');
$iDraftUid = (int) $this->GetActionParam('MessageUid', 0); $iDraftUid = (int) $this->GetActionParam('MessageUid', 0);
if (\strlen($sDraftFolder) && 0 < $iDraftUid) if (\strlen($sDraftFolder) && 0 < $iDraftUid) {
{
try try
{ {
$this->MailClient()->MessageDelete($sDraftFolder, new SequenceSet($iDraftUid)); $this->MailClient()->MessageDelete($sDraftFolder, new SequenceSet($iDraftUid));
@ -284,27 +262,22 @@ trait Messages
throw new ClientException(Notifications::CantSendMessage, $oException); throw new ClientException(Notifications::CantSendMessage, $oException);
} }
if (false === $mResult) if (false === $mResult) {
{
throw new ClientException(Notifications::CantSendMessage); throw new ClientException(Notifications::CantSendMessage);
} }
try try
{ {
if ($oMessage && $this->AddressBookProvider($oAccount)->IsActive()) if ($oMessage && $this->AddressBookProvider($oAccount)->IsActive()) {
{
$aArrayToFrec = array(); $aArrayToFrec = array();
$oToCollection = $oMessage->GetTo(); $oToCollection = $oMessage->GetTo();
if ($oToCollection) if ($oToCollection) {
{ foreach ($oToCollection as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) {
foreach ($oToCollection as /* @var $oEmail \MailSo\Mime\Email */ $oEmail)
{
$aArrayToFrec[$oEmail->GetEmail(true)] = $oEmail->ToString(false, true); $aArrayToFrec[$oEmail->GetEmail(true)] = $oEmail->ToString(false, true);
} }
} }
if (\count($aArrayToFrec)) if (\count($aArrayToFrec)) {
{
$oSettings = $this->SettingsProvider()->Load($oAccount); $oSettings = $this->SettingsProvider()->Load($oAccount);
$this->AddressBookProvider($oAccount)->IncFrec( $this->AddressBookProvider($oAccount)->IncFrec(
@ -319,7 +292,7 @@ trait Messages
$this->Logger()->WriteException($oException); $this->Logger()->WriteException($oException);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoSendReadReceiptMessage() : array public function DoSendReadReceiptMessage() : array
@ -333,19 +306,16 @@ trait Messages
$mResult = false; $mResult = false;
try try
{ {
if ($oMessage) if ($oMessage) {
{
$rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource(); $rMessageStream = \MailSo\Base\ResourceRegistry::CreateMemoryResource();
$iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter( $iMessageStreamSize = \MailSo\Base\Utils::MultipleStreamWriter(
$oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true); $oMessage->ToStream(true), array($rMessageStream), 8192, true, true, true);
if (false !== $iMessageStreamSize) if (false !== $iMessageStreamSize) {
{
$this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, false, false); $this->smtpSendMessage($oAccount, $oMessage, $rMessageStream, $iMessageStreamSize, false, false);
if (\is_resource($rMessageStream)) if (\is_resource($rMessageStream)) {
{
\fclose($rMessageStream); \fclose($rMessageStream);
} }
@ -356,8 +326,7 @@ trait Messages
$this->Cacher($oAccount)->Set(\RainLoop\KeyPathHelper::ReadReceiptCache($oAccount->Email(), $sFolderFullName, $iUid), '1'); $this->Cacher($oAccount)->Set(\RainLoop\KeyPathHelper::ReadReceiptCache($oAccount->Email(), $sFolderFullName, $iUid), '1');
if (\strlen($sFolderFullName) && 0 < $iUid) if (\strlen($sFolderFullName) && 0 < $iUid) {
{
try try
{ {
$this->MailClient()->MessageSetFlag($sFolderFullName, new SequenceSet($iUid), MessageFlag::MDNSENT, true, true); $this->MailClient()->MessageSetFlag($sFolderFullName, new SequenceSet($iUid), MessageFlag::MDNSENT, true, true);
@ -376,17 +345,16 @@ trait Messages
throw new ClientException(Notifications::CantSendMessage, $oException); throw new ClientException(Notifications::CantSendMessage, $oException);
} }
if (false === $mResult) if (false === $mResult) {
{
throw new ClientException(Notifications::CantSendMessage); throw new ClientException(Notifications::CantSendMessage);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoMessageSetSeen() : array public function DoMessageSetSeen() : array
{ {
return $this->messageSetFlag(MessageFlag::SEEN, __FUNCTION__); return $this->messageSetFlag(MessageFlag::SEEN);
} }
public function DoMessageSetSeenToAll() : array public function DoMessageSetSeenToAll() : array
@ -409,17 +377,17 @@ trait Messages
throw new ClientException(Notifications::MailServerError, $oException); throw new ClientException(Notifications::MailServerError, $oException);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoMessageSetFlagged() : array public function DoMessageSetFlagged() : array
{ {
return $this->messageSetFlag(MessageFlag::FLAGGED, __FUNCTION__, true); return $this->messageSetFlag(MessageFlag::FLAGGED, true);
} }
public function DoMessageSetKeyword() : array public function DoMessageSetKeyword() : array
{ {
return $this->messageSetFlag($this->GetActionParam('Keyword', ''), __FUNCTION__, true); return $this->messageSetFlag($this->GetActionParam('Keyword', ''), true);
} }
/** /**
@ -433,15 +401,12 @@ trait Messages
$iUid = 0; $iUid = 0;
$aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey), true); $aValues = \json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey), true);
if ($aValues && 2 <= \count($aValues)) if ($aValues && 2 <= \count($aValues)) {
{
$sFolder = (string) $aValues[0]; $sFolder = (string) $aValues[0];
$iUid = (int) $aValues[1]; $iUid = (int) $aValues[1];
$this->verifyCacheByKey($sRawKey); $this->verifyCacheByKey($sRawKey);
} } else {
else
{
$sFolder = $this->GetActionParam('Folder', ''); $sFolder = $this->GetActionParam('Folder', '');
$iUid = (int) $this->GetActionParam('Uid', 0); $iUid = (int) $this->GetActionParam('Uid', 0);
} }
@ -457,14 +422,13 @@ trait Messages
throw new ClientException(Notifications::CantGetMessage, $oException); throw new ClientException(Notifications::CantGetMessage, $oException);
} }
if ($oMessage) if ($oMessage) {
{
$this->Plugins()->RunHook('filter.result-message', array($oMessage)); $this->Plugins()->RunHook('filter.result-message', array($oMessage));
$this->cacheByKey($sRawKey); $this->cacheByKey($sRawKey);
} }
return $this->DefaultResponse(__FUNCTION__, $oMessage); return $this->DefaultResponse($oMessage);
} }
/** /**
@ -496,7 +460,7 @@ trait Messages
\SnappyMail\Log::warning('IMAP', "FolderHash({$sFolder}) Exception: {$oException->getMessage()}"); \SnappyMail\Log::warning('IMAP', "FolderHash({$sFolder}) Exception: {$oException->getMessage()}");
} }
return $this->DefaultResponse(__FUNCTION__, $sHash ? array($sFolder, $sHash) : array($sFromFolder)); return $this->DefaultResponse($sHash ? array($sFolder, $sHash) : array($sFromFolder));
} }
/** /**
@ -511,8 +475,7 @@ trait Messages
$oUids = new SequenceSet(\explode(',', (string) $this->GetActionParam('Uids', ''))); $oUids = new SequenceSet(\explode(',', (string) $this->GetActionParam('Uids', '')));
if (!empty($this->GetActionParam('MarkAsRead', '0'))) if (!empty($this->GetActionParam('MarkAsRead', '0'))) {
{
try try
{ {
$this->MailClient()->MessageSetFlag($sFromFolder, $oUids, MessageFlag::SEEN); $this->MailClient()->MessageSetFlag($sFromFolder, $oUids, MessageFlag::SEEN);
@ -524,8 +487,7 @@ trait Messages
} }
$sLearning = $this->GetActionParam('Learning', ''); $sLearning = $this->GetActionParam('Learning', '');
if ($sLearning) if ($sLearning) {
{
try try
{ {
if ('SPAM' === $sLearning) { if ('SPAM' === $sLearning) {
@ -561,7 +523,7 @@ trait Messages
\SnappyMail\Log::warning('IMAP', "FolderHash({$sFromFolder}) Exception: {$oException->getMessage()}"); \SnappyMail\Log::warning('IMAP', "FolderHash({$sFromFolder}) Exception: {$oException->getMessage()}");
} }
return $this->DefaultResponse(__FUNCTION__, $sHash ? array($sFromFolder, $sHash) : array($sFromFolder)); return $this->DefaultResponse($sHash ? array($sFromFolder, $sHash) : array($sFromFolder));
} }
/** /**
@ -584,7 +546,7 @@ trait Messages
throw new ClientException(Notifications::CantCopyMessage, $oException); throw new ClientException(Notifications::CantCopyMessage, $oException);
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoMessageUploadAttachments() : array public function DoMessageUploadAttachments() : array
@ -654,7 +616,7 @@ trait Messages
throw new ClientException(Notifications::MailServerError, $oException); throw new ClientException(Notifications::MailServerError, $oException);
} }
return $this->DefaultResponse(__FUNCTION__, $aAttachments); return $this->DefaultResponse($aAttachments);
} }
/** /**
@ -770,7 +732,7 @@ trait Messages
} }
} }
return $this->DefaultResponse(__FUNCTION__, $result); return $this->DefaultResponse($result);
} }
/** /**
@ -810,16 +772,12 @@ trait Messages
$bUsePhpMail = false; $bUsePhpMail = false;
$oAccount->SmtpConnectAndLoginHelper($this->Plugins(), $oSmtpClient, $this->Config(), $bUsePhpMail); $oAccount->SmtpConnectAndLoginHelper($this->Plugins(), $oSmtpClient, $this->Config(), $bUsePhpMail);
if ($bUsePhpMail) if ($bUsePhpMail) {
{ if (\MailSo\Base\Utils::FunctionCallable('mail')) {
if (\MailSo\Base\Utils::FunctionCallable('mail'))
{
$aToCollection = $oMessage->GetTo(); $aToCollection = $oMessage->GetTo();
if ($aToCollection && $oFrom) if ($aToCollection && $oFrom) {
{
$sRawBody = \stream_get_contents($rMessageStream); $sRawBody = \stream_get_contents($rMessageStream);
if (!empty($sRawBody)) if (!empty($sRawBody)) {
{
$sMailTo = \trim($aToCollection->ToString(true)); $sMailTo = \trim($aToCollection->ToString(true));
$sMailSubject = \trim($oMessage->GetSubject()); $sMailSubject = \trim($oMessage->GetSubject());
$sMailSubject = 0 === \strlen($sMailSubject) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue( $sMailSubject = 0 === \strlen($sMailSubject) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
@ -829,8 +787,7 @@ trait Messages
list($sMailHeaders, $sMailBody) = \explode("\r\n\r\n", $sRawBody, 2); list($sMailHeaders, $sMailBody) = \explode("\r\n\r\n", $sRawBody, 2);
unset($sRawBody); unset($sRawBody);
if ($this->Config()->Get('labs', 'mail_func_clear_headers', true)) if ($this->Config()->Get('labs', 'mail_func_clear_headers', true)) {
{
$sMailHeaders = \MailSo\Base\Utils::RemoveHeaderFromHeaders($sMailHeaders, array( $sMailHeaders = \MailSo\Base\Utils::RemoveHeaderFromHeaders($sMailHeaders, array(
MimeEnumHeader::TO_, MimeEnumHeader::TO_,
MimeEnumHeader::SUBJECT MimeEnumHeader::SUBJECT
@ -845,20 +802,15 @@ trait Messages
\mail($sMailTo, $sMailSubject, $sMailBody, $sMailHeaders, '-f'.$oFrom->GetEmail()) : \mail($sMailTo, $sMailSubject, $sMailBody, $sMailHeaders, '-f'.$oFrom->GetEmail()) :
\mail($sMailTo, $sMailSubject, $sMailBody, $sMailHeaders); \mail($sMailTo, $sMailSubject, $sMailBody, $sMailHeaders);
if (!$bR) if (!$bR) {
{
throw new ClientException(Notifications::CantSendMessage); throw new ClientException(Notifications::CantSendMessage);
} }
} }
} }
} } else {
else
{
throw new ClientException(Notifications::CantSendMessage); throw new ClientException(Notifications::CantSendMessage);
} }
} } else if ($oSmtpClient->IsConnected()) {
else if ($oSmtpClient->IsConnected())
{
if ($iMessageStreamSize && $oSmtpClient->maxSize() && $iMessageStreamSize * 1.33 > $oSmtpClient->maxSize()) { if ($iMessageStreamSize && $oSmtpClient->maxSize() && $iMessageStreamSize * 1.33 > $oSmtpClient->maxSize()) {
throw new ClientException(Notifications::ClientViewError, 'Message size '. ($iMessageStreamSize * 1.33) . ' bigger then max ' . $oSmtpClient->maxSize()); throw new ClientException(Notifications::ClientViewError, 'Message size '. ($iMessageStreamSize * 1.33) . ' bigger then max ' . $oSmtpClient->maxSize());
} }
@ -904,7 +856,7 @@ trait Messages
} }
} }
private function messageSetFlag(string $sMessageFlag, string $sResponseFunction, bool $bSkipUnsupportedFlag = false) : array private function messageSetFlag(string $sMessageFlag, bool $bSkipUnsupportedFlag = false) : array
{ {
$this->initMailClientConnection(); $this->initMailClientConnection();
@ -923,19 +875,16 @@ trait Messages
throw new ClientException(Notifications::MailServerError, $oException); throw new ClientException(Notifications::MailServerError, $oException);
} }
return $this->TrueResponse($sResponseFunction); return $this->TrueResponse();
} }
private function deleteMessageAttachments(Account $oAccount) : void private function deleteMessageAttachments(Account $oAccount) : void
{ {
$aAttachments = $this->GetActionParam('Attachments', null); $aAttachments = $this->GetActionParam('Attachments', null);
if (\is_array($aAttachments)) if (\is_array($aAttachments)) {
{ foreach (\array_keys($aAttachments) as $sTempName) {
foreach (\array_keys($aAttachments) as $sTempName) if ($this->FilesProvider()->FileExists($oAccount, $sTempName)) {
{
if ($this->FilesProvider()->FileExists($oAccount, $sTempName))
{
$this->FilesProvider()->Clear($oAccount, $sTempName); $this->FilesProvider()->Clear($oAccount, $sTempName);
} }
} }
@ -1080,8 +1029,7 @@ trait Messages
} }
$aDraftInfo = $this->GetActionParam('DraftInfo', null); $aDraftInfo = $this->GetActionParam('DraftInfo', null);
if ($bWithDraftInfo && \is_array($aDraftInfo) && !empty($aDraftInfo[0]) && !empty($aDraftInfo[1]) && !empty($aDraftInfo[2])) if ($bWithDraftInfo && \is_array($aDraftInfo) && !empty($aDraftInfo[0]) && !empty($aDraftInfo[1]) && !empty($aDraftInfo[2])) {
{
$oMessage->SetDraftInfo($aDraftInfo[0], $aDraftInfo[1], $aDraftInfo[2]); $oMessage->SetDraftInfo($aDraftInfo[0], $aDraftInfo[1], $aDraftInfo[2]);
} }
@ -1217,10 +1165,8 @@ trait Messages
unset($oPart); unset($oPart);
$aAttachments = $this->GetActionParam('Attachments', null); $aAttachments = $this->GetActionParam('Attachments', null);
if (\is_array($aAttachments)) if (\is_array($aAttachments)) {
{ foreach ($aAttachments as $sTempName => $aData) {
foreach ($aAttachments as $sTempName => $aData)
{
$sFileName = (string) $aData['name']; $sFileName = (string) $aData['name'];
$bIsInline = (bool) $aData['inline']; $bIsInline = (bool) $aData['inline'];
$sCID = (string) $aData['cid']; $sCID = (string) $aData['cid'];
@ -1228,8 +1174,7 @@ trait Messages
$sMimeType = (string) $aData['type']; $sMimeType = (string) $aData['type'];
$rResource = $this->FilesProvider()->GetFile($oAccount, $sTempName); $rResource = $this->FilesProvider()->GetFile($oAccount, $sTempName);
if (\is_resource($rResource)) if (\is_resource($rResource)) {
{
$iFileSize = $this->FilesProvider()->FileSize($oAccount, $sTempName); $iFileSize = $this->FilesProvider()->FileSize($oAccount, $sTempName);
$oMessage->Attachments()->append( $oMessage->Attachments()->append(
@ -1242,8 +1187,7 @@ trait Messages
} }
} }
foreach ($aFoundDataURL as $sCidHash => $sDataUrlString) foreach ($aFoundDataURL as $sCidHash => $sDataUrlString) {
{
$aMatch = array(); $aMatch = array();
$sCID = '<'.$sCidHash.'>'; $sCID = '<'.$sCidHash.'>';
if (\preg_match('/^data:(image\/[a-zA-Z0-9]+);base64,(.+)$/i', $sDataUrlString, $aMatch) && if (\preg_match('/^data:(image\/[a-zA-Z0-9]+);base64,(.+)$/i', $sDataUrlString, $aMatch) &&
@ -1251,8 +1195,7 @@ trait Messages
{ {
$sRaw = \MailSo\Base\Utils::Base64Decode($aMatch[2]); $sRaw = \MailSo\Base\Utils::Base64Decode($aMatch[2]);
$iFileSize = \strlen($sRaw); $iFileSize = \strlen($sRaw);
if (0 < $iFileSize) if (0 < $iFileSize) {
{
$sFileName = \preg_replace('/[^a-z0-9]+/i', '.', $aMatch[1]); $sFileName = \preg_replace('/[^a-z0-9]+/i', '.', $aMatch[1]);
$rResource = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString($sRaw); $rResource = \MailSo\Base\ResourceRegistry::CreateMemoryResourceFromString($sRaw);

View file

@ -74,7 +74,7 @@ trait Pgp
{ {
$GPG = $this->GnuPG(); $GPG = $this->GnuPG();
if (!$GPG) { if (!$GPG) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$GPG->addDecryptKey( $GPG->addDecryptKey(
@ -113,19 +113,19 @@ trait Pgp
// $result['signatures'] = $oPart->SubParts[0]; // $result['signatures'] = $oPart->SubParts[0];
} }
return $this->DefaultResponse(__FUNCTION__, $result); return $this->DefaultResponse($result);
} }
public function DoGnupgGetKeys() : array public function DoGnupgGetKeys() : array
{ {
$GPG = $this->GnuPG(); $GPG = $this->GnuPG();
return $this->DefaultResponse(__FUNCTION__, $GPG ? $GPG->keyInfo('') : false); return $this->DefaultResponse($GPG ? $GPG->keyInfo('') : false);
} }
public function DoGnupgExportKey() : array public function DoGnupgExportKey() : array
{ {
$GPG = $this->GnuPG(); $GPG = $this->GnuPG();
return $this->DefaultResponse(__FUNCTION__, $GPG ? $GPG->export( return $this->DefaultResponse($GPG ? $GPG->export(
$this->GetActionParam('KeyId', ''), $this->GetActionParam('KeyId', ''),
$this->GetActionParam('Passphrase', '') $this->GetActionParam('Passphrase', '')
) : false); ) : false);
@ -143,7 +143,7 @@ trait Pgp
$this->GetActionParam('Passphrase', '') $this->GetActionParam('Passphrase', '')
); );
} }
return $this->DefaultResponse(__FUNCTION__, $fingerprint); return $this->DefaultResponse($fingerprint);
} }
public function DoGnupgDeleteKey() : array public function DoGnupgDeleteKey() : array
@ -151,7 +151,7 @@ trait Pgp
$GPG = $this->GnuPG(); $GPG = $this->GnuPG();
$sKeyId = $this->GetActionParam('KeyId', ''); $sKeyId = $this->GetActionParam('KeyId', '');
$bPrivate = !!$this->GetActionParam('isPrivate', 0); $bPrivate = !!$this->GetActionParam('isPrivate', 0);
return $this->DefaultResponse(__FUNCTION__, $GPG ? $GPG->deleteKey($sKeyId, $bPrivate) : false); return $this->DefaultResponse($GPG ? $GPG->deleteKey($sKeyId, $bPrivate) : false);
} }
public function DoGnupgImportKey() : array public function DoGnupgImportKey() : array
@ -182,7 +182,7 @@ trait Pgp
} }
$GPG = $sKey ? $this->GnuPG() : null; $GPG = $sKey ? $this->GnuPG() : null;
return $this->DefaultResponse(__FUNCTION__, $GPG ? $GPG->import($sKey) : false); return $this->DefaultResponse($GPG ? $GPG->import($sKey) : false);
} }
/** /**
@ -219,7 +219,7 @@ trait Pgp
} }
} }
return $this->DefaultResponse(__FUNCTION__, $keys); return $this->DefaultResponse($keys);
} }
/** /**
@ -256,7 +256,7 @@ trait Pgp
} }
// $revocationCertificate = $this->GetActionParam('revocationCertificate', ''); // $revocationCertificate = $this->GetActionParam('revocationCertificate', '');
return $this->DefaultResponse(__FUNCTION__, $result); return $this->DefaultResponse($result);
} }
/** /**
@ -267,7 +267,7 @@ trait Pgp
{ {
$key = $this->GetActionParam('Key', ''); $key = $this->GetActionParam('Key', '');
$keyId = $this->GetActionParam('KeyId', ''); $keyId = $this->GetActionParam('KeyId', '');
return $this->DefaultResponse(__FUNCTION__, ($key && $keyId && $this->StorePGPKey($key, $keyId))); return $this->DefaultResponse(($key && $keyId && $this->StorePGPKey($key, $keyId)));
} }
private function StorePGPKey(string $key, string $keyId = '') : bool private function StorePGPKey(string $key, string $keyId = '') : bool

View file

@ -83,8 +83,7 @@ trait Raw
$sHash = $sRawKey; $sHash = $sRawKey;
$sData = ''; $sData = '';
if (!empty($sHash)) if (!empty($sHash)) {
{
$sData = $this->StorageProvider()->Get(null, $sData = $this->StorageProvider()->Get(null,
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
\RainLoop\KeyPathHelper::PublicFile($sHash) \RainLoop\KeyPathHelper::PublicFile($sHash)
@ -96,8 +95,7 @@ trait Raw
\preg_match('/^data:([^:]+):/', $sData, $aMatch) && !empty($aMatch[1])) \preg_match('/^data:([^:]+):/', $sData, $aMatch) && !empty($aMatch[1]))
{ {
$sContentType = \trim($aMatch[1]); $sContentType = \trim($aMatch[1]);
if (\in_array($sContentType, array('image/png', 'image/jpg', 'image/jpeg'))) if (\in_array($sContentType, array('image/png', 'image/jpg', 'image/jpeg'))) {
{
$this->cacheByKey($sRawKey); $this->cacheByKey($sRawKey);
\header('Content-Type: '.$sContentType); \header('Content-Type: '.$sContentType);
@ -123,7 +121,8 @@ trait Raw
$sRangeStart = $sRangeEnd = ''; $sRangeStart = $sRangeEnd = '';
$bIsRangeRequest = false; $bIsRangeRequest = false;
if (!empty($sRange) && 'bytes=0-' !== \strtolower($sRange) && \preg_match('/^bytes=([0-9]+)-([0-9]*)/i', \trim($sRange), $aMatch)) if (!empty($sRange) && 'bytes=0-' !== \strtolower($sRange)
&& \preg_match('/^bytes=([0-9]+)-([0-9]*)/i', \trim($sRange), $aMatch))
{ {
$sRangeStart = $aMatch[1]; $sRangeStart = $aMatch[1];
$sRangeEnd = $aMatch[2]; $sRangeEnd = $aMatch[2];
@ -139,8 +138,7 @@ trait Raw
$sFileNameIn = isset($aValues['FileName']) ? (string) $aValues['FileName'] : ''; $sFileNameIn = isset($aValues['FileName']) ? (string) $aValues['FileName'] : '';
$sFileHashIn = isset($aValues['FileHash']) ? (string) $aValues['FileHash'] : ''; $sFileHashIn = isset($aValues['FileHash']) ? (string) $aValues['FileHash'] : '';
if (!empty($sFileHashIn)) if (!empty($sFileHashIn)) {
{
$this->verifyCacheByKey($sRawKey); $this->verifyCacheByKey($sRawKey);
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
@ -185,8 +183,7 @@ trait Raw
$self, $oAccount, $sRawKey, $sContentTypeIn, $sFileNameIn, $bDownload, $bThumbnail, $self, $oAccount, $sRawKey, $sContentTypeIn, $sFileNameIn, $bDownload, $bThumbnail,
$bIsRangeRequest, $sRangeStart, $sRangeEnd $bIsRangeRequest, $sRangeStart, $sRangeEnd
) { ) {
if ($oAccount && \is_resource($rResource)) if ($oAccount && \is_resource($rResource)) {
{
\MailSo\Base\Utils::ResetTimeLimit(); \MailSo\Base\Utils::ResetTimeLimit();
$self->cacheByKey($sRawKey); $self->cacheByKey($sRawKey);
@ -207,24 +204,20 @@ trait Raw
?: 'application/octet-stream'; ?: 'application/octet-stream';
} }
if (!$bDownload) if (!$bDownload) {
{
$bDetectImageOrientation = $self->Config()->Get('labs', 'image_exif_auto_rotate', false) $bDetectImageOrientation = $self->Config()->Get('labs', 'image_exif_auto_rotate', false)
// Mostly only JPEG has EXIF metadata // Mostly only JPEG has EXIF metadata
&& 'image/jpeg' == $sContentType; && 'image/jpeg' == $sContentType;
try try
{ {
if ($bThumbnail) if ($bThumbnail) {
{
$oImage = static::loadImage($rResource, $bDetectImageOrientation, 48); $oImage = static::loadImage($rResource, $bDetectImageOrientation, 48);
\header('Content-Disposition: inline; '. \header('Content-Disposition: inline; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName.'_thumb60x60.png'))); \trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName.'_thumb60x60.png')));
$oImage->show('png'); $oImage->show('png');
// $oImage->show('webp'); // Little Britain: "Safari says NO" // $oImage->show('webp'); // Little Britain: "Safari says NO"
exit; exit;
} } else if ($bDetectImageOrientation) {
else if ($bDetectImageOrientation)
{
$oImage = static::loadImage($rResource, $bDetectImageOrientation); $oImage = static::loadImage($rResource, $bDetectImageOrientation);
\header('Content-Disposition: inline; '. \header('Content-Disposition: inline; '.
\trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName))); \trim(\MailSo\Base\Utils::EncodeHeaderUtf8AttributeValue('filename', $sFileName)));
@ -263,24 +256,20 @@ trait Raw
\MailSo\Base\Http::StatusHeader(206); \MailSo\Base\Http::StatusHeader(206);
$iRangeStart = (int) $sRangeStart; $iRangeStart = \max(0, \intval($sRangeStart));
$iRangeEnd = (int) $sRangeEnd; $iRangeEnd = \max(0, \intval($sRangeEnd));
if ('' === $sRangeEnd) { if ($iRangeEnd && $iRangeStart < $iRangeEnd) {
$sLoadedData = 0 < $iRangeStart ? \substr($sLoadedData, $iRangeStart) : $sLoadedData;
} else {
if ($iRangeStart < $iRangeEnd) {
$sLoadedData = \substr($sLoadedData, $iRangeStart, $iRangeEnd - $iRangeStart); $sLoadedData = \substr($sLoadedData, $iRangeStart, $iRangeEnd - $iRangeStart);
} else { } else if ($iRangeStart) {
$sLoadedData = 0 < $iRangeStart ? \substr($sLoadedData, $iRangeStart) : $sLoadedData; $sLoadedData = \substr($sLoadedData, $iRangeStart);
}
} }
$iContentLength = \strlen($sLoadedData); $iContentLength = \strlen($sLoadedData);
if (0 < $iContentLength) { if (0 < $iContentLength) {
\header('Content-Length: '.$iContentLength); \header('Content-Length: '.$iContentLength);
\header('Content-Range: bytes '.$sRangeStart.'-'.(0 < $iRangeEnd ? $iRangeEnd : $iFullContentLength - 1).'/'.$iFullContentLength); \header('Content-Range: bytes '.$sRangeStart.'-'.($iRangeEnd ?: $iFullContentLength - 1).'/'.$iFullContentLength);
} }
} else { } else {
\header('Content-Length: '.\strlen($sLoadedData)); \header('Content-Length: '.\strlen($sLoadedData));

View file

@ -9,98 +9,64 @@ use RainLoop\Utils;
trait Response trait Response
{ {
/** /**
* @param mixed $mResult = false * @param mixed $mResult
*/ */
public function DefaultResponse(string $sActionName, $mResult = false, array $aAdditionalParams = array()) : array public function DefaultResponse($mResult, array $aAdditionalParams = array(), string $sActionName = '') : array
{ {
$this->Plugins()->RunHook('main.default-response-data', array($sActionName, &$mResult)); if (false === $mResult) {
$aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams); if (!isset($aAdditionalParams['ErrorCode'])) {
$this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); $aAdditionalParams['ErrorCode'] = 0;
return $aResponseItem; }
if (!isset($aAdditionalParams['ErrorMessage'])) {
$aAdditionalParams['ErrorMessage'] = '';
}
} }
public function TrueResponse(string $sActionName, array $aAdditionalParams = array()) : array return \array_merge(array(
{ // 'Version' => APP_VERSION,
$mResult = true; 'Action' => $sActionName,
$this->Plugins()->RunHook('main.default-response-data', array($sActionName, &$mResult)); 'Result' => $this->responseObject($mResult)
$aResponseItem = $this->mainDefaultResponse($sActionName, $mResult, $aAdditionalParams); ), $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 public function TrueResponse(array $aAdditionalParams = array()) : array
{ {
$mResult = false; return $this->DefaultResponse(true, $aAdditionalParams);
$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); public function FalseResponse(int $iErrorCode = 0, string $sErrorMessage = '', string $sAdditionalErrorMessage = '') : array
{
$this->Plugins()->RunHook('main.default-response', array($sActionName, &$aResponseItem)); return $this->DefaultResponse(false, [
return $aResponseItem; 'ErrorCode' => $iErrorCode,
'ErrorMessage' => $sErrorMessage,
'ErrorMessageAdditional' => $sAdditionalErrorMessage
]);
} }
public function ExceptionResponse(string $sActionName, \Throwable $oException) : array public function ExceptionResponse(\Throwable $oException) : array
{ {
$iErrorCode = null; $iErrorCode = 0;
$sErrorMessage = null; $sErrorMessage = '';
$sErrorMessageAdditional = null; $sErrorMessageAdditional = '';
if ($oException instanceof \RainLoop\Exceptions\ClientException) { if ($oException instanceof \RainLoop\Exceptions\ClientException) {
$iErrorCode = $oException->getCode(); $iErrorCode = $oException->getCode();
$sErrorMessage = null;
if ($iErrorCode === Notifications::ClientViewError) { if ($iErrorCode === Notifications::ClientViewError) {
$sErrorMessage = $oException->getMessage(); $sErrorMessage = $oException->getMessage();
} }
$sErrorMessageAdditional = $oException->getAdditionalMessage(); $sErrorMessageAdditional = $oException->getAdditionalMessage();
if (empty($sErrorMessageAdditional)) {
$sErrorMessageAdditional = null;
}
} else { } else {
$iErrorCode = Notifications::UnknownError; $iErrorCode = Notifications::UnknownError;
$sErrorMessage = $oException->getCode().' - '.$oException->getMessage(); $sErrorMessage = $oException->getCode().' - '.$oException->getMessage();
} }
$oPrevious = $oException->getPrevious(); $this->Logger()->WriteException($oException->getPrevious() ?: $oException);
if ($oPrevious) {
$this->Logger()->WriteException($oPrevious);
} else {
$this->Logger()->WriteException($oException);
}
return $this->FalseResponse($sActionName, $iErrorCode, $sErrorMessage, $sErrorMessageAdditional); return $this->DefaultResponse(false, [
} 'ErrorCode' => $iErrorCode,
'ErrorMessage' => $sErrorMessage,
/** 'ErrorMessageAdditional' => $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(
// 'Version' => APP_VERSION,
'Action' => $sActionName,
'Result' => $this->responseObject($mResult, $sActionName)
);
foreach ($aAdditionalParams as $sKey => $mValue) {
$aResult[$sKey] = $mValue;
}
return $aResult;
} }
private function isFileHasThumbnail(string $sFileName) : bool private function isFileHasThumbnail(string $sFileName) : bool
@ -138,7 +104,7 @@ trait Response
if (\is_array($mResponse)) { if (\is_array($mResponse)) {
foreach ($mResponse as $iKey => $oItem) { foreach ($mResponse as $iKey => $oItem) {
$mResponse[$iKey] = $this->responseObject($oItem, $sParent); $mResponse[$iKey] = $this->responseObject($oItem, 'Array');
} }
} }
@ -159,7 +125,7 @@ trait Response
// \MailSo\Mime\EmailCollection // \MailSo\Mime\EmailCollection
foreach (['ReplyTo','From','To','Cc','Bcc','Sender','DeliveredTo'] as $prop) { foreach (['ReplyTo','From','To','Cc','Bcc','Sender','DeliveredTo'] as $prop) {
$mResult[$prop] = $this->responseObject($mResult[$prop], $sParent); $mResult[$prop] = $this->responseObject($mResult[$prop], $prop);
} }
$sSubject = $mResult['subject']; $sSubject = $mResult['subject'];
@ -172,9 +138,9 @@ trait Response
'FileName' => (\strlen($sSubject) ? \MailSo\Base\Utils::SecureFileName($sSubject) : 'message-'.$mResult['Uid']) . '.eml' 'FileName' => (\strlen($sSubject) ? \MailSo\Base\Utils::SecureFileName($sSubject) : 'message-'.$mResult['Uid']) . '.eml'
)); ));
$mResult['Attachments'] = $this->responseObject($mResponse->Attachments, $sParent); $mResult['Attachments'] = $this->responseObject($mResponse->Attachments, 'Attachments');
if ('Message' === $sParent) { if (!$sParent) {
$mResult['DraftInfo'] = $mResponse->DraftInfo; $mResult['DraftInfo'] = $mResponse->DraftInfo;
$mResult['InReplyTo'] = $mResponse->InReplyTo; $mResult['InReplyTo'] = $mResponse->InReplyTo;
$mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks; $mResult['UnsubsribeLinks'] = $mResponse->UnsubsribeLinks;
@ -188,7 +154,6 @@ trait Response
$mResult['PgpEncrypted'] = $mResponse->pgpEncrypted; $mResult['PgpEncrypted'] = $mResponse->pgpEncrypted;
$mResult['ReadReceipt'] = $mResponse->ReadReceipt; $mResult['ReadReceipt'] = $mResponse->ReadReceipt;
if (\strlen($mResult['ReadReceipt']) && !\in_array('$forwarded', $mResult['Flags'])) { if (\strlen($mResult['ReadReceipt']) && !\in_array('$forwarded', $mResult['Flags'])) {
// \in_array('$mdnsent', $mResult['Flags']) // \in_array('$mdnsent', $mResult['Flags'])
if (\strlen($mResult['ReadReceipt'])) { if (\strlen($mResult['ReadReceipt'])) {
@ -249,7 +214,7 @@ trait Response
if ($mResponse instanceof \MailSo\Base\Collection) { if ($mResponse instanceof \MailSo\Base\Collection) {
$mResult = $mResponse->jsonSerialize(); $mResult = $mResponse->jsonSerialize();
$mResult['@Collection'] = $this->responseObject($mResult['@Collection'], $sParent); $mResult['@Collection'] = $this->responseObject($mResult['@Collection'], 'Collection');
if ($mResponse instanceof \MailSo\Mail\EmailCollection) { if ($mResponse instanceof \MailSo\Mail\EmailCollection) {
return \array_slice($mResult['@Collection'], 0, 100); return \array_slice($mResult['@Collection'], 0, 100);
} }

View file

@ -133,7 +133,7 @@ trait Themes
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(\RainLoop\Enumerations\Capa::USER_BACKGROUND)) { if (!$this->GetCapa(\RainLoop\Enumerations\Capa::USER_BACKGROUND)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$sName = ''; $sName = '';
@ -200,13 +200,12 @@ trait Themes
if (UPLOAD_ERR_OK !== $iError) { if (UPLOAD_ERR_OK !== $iError) {
$iClientError = \RainLoop\Enumerations\UploadError::NORMAL; $iClientError = \RainLoop\Enumerations\UploadError::NORMAL;
$sError = $this->getUploadErrorMessageByCode($iError, $iClientError); $sError = $this->getUploadErrorMessageByCode($iError, $iClientError);
if (!empty($sError)) { if (!empty($sError)) {
return $this->FalseResponse(__FUNCTION__, $iClientError, $sError); return $this->FalseResponse($iClientError, $sError);
} }
} }
return $this->DefaultResponse(__FUNCTION__, !empty($sName) && !empty($sHash) ? array( return $this->DefaultResponse(!empty($sName) && !empty($sHash) ? array(
'Name' => $sName, 'Name' => $sName,
'Hash' => $sHash 'Hash' => $sHash
) : false); ) : false);

View file

@ -60,7 +60,7 @@ trait User
} }
} }
return $this->DefaultResponse(__FUNCTION__, $this->AppData(false)); return $this->DefaultResponse($this->AppData(false));
} }
public function DoLogout() : array public function DoLogout() : array
@ -68,7 +68,7 @@ trait User
$bMain = true; // empty($_COOKIE[self::AUTH_ADDITIONAL_TOKEN_KEY]); $bMain = true; // empty($_COOKIE[self::AUTH_ADDITIONAL_TOKEN_KEY]);
$this->Logout($bMain); $this->Logout($bMain);
$bMain && $this->ClearSignMeData(); $bMain && $this->ClearSignMeData();
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoAppDelayStart() : array public function DoAppDelayStart() : array
@ -126,7 +126,7 @@ trait User
$this->Plugins()->RunHook('service.app-delay-start-end'); $this->Plugins()->RunHook('service.app-delay-start-end');
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoSettingsUpdate() : array public function DoSettingsUpdate() : array
@ -201,8 +201,7 @@ trait User
$this->setSettingsFromParams($oSettingsLocal, 'HideDeleted', 'bool'); $this->setSettingsFromParams($oSettingsLocal, 'HideDeleted', 'bool');
$this->setSettingsFromParams($oSettingsLocal, 'UnhideKolabFolders', 'bool'); $this->setSettingsFromParams($oSettingsLocal, 'UnhideKolabFolders', 'bool');
return $this->DefaultResponse(__FUNCTION__, return $this->DefaultResponse($this->SettingsProvider()->Save($oAccount, $oSettings) &&
$this->SettingsProvider()->Save($oAccount, $oSettings) &&
$this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal)); $this->SettingsProvider(true)->Save($oAccount, $oSettingsLocal));
} }
@ -211,7 +210,7 @@ trait User
$oAccount = $this->initMailClientConnection(); $oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(Capa::QUOTA)) { if (!$this->GetCapa(Capa::QUOTA)) {
return $this->DefaultResponse(__FUNCTION__, array(0, 0, 0, 0)); return $this->DefaultResponse(array(0, 0, 0, 0));
} }
try try
@ -223,7 +222,7 @@ trait User
throw new ClientException(Notifications::MailServerError, $oException); throw new ClientException(Notifications::MailServerError, $oException);
} }
return $this->DefaultResponse(__FUNCTION__, $aQuota); return $this->DefaultResponse($aQuota);
} }
public function DoSuggestions() : array public function DoSuggestions() : array
@ -275,7 +274,7 @@ trait User
$aResult = \array_slice(\array_values($aResult), 0, $iLimit); $aResult = \array_slice(\array_values($aResult), 0, $iLimit);
} }
return $this->DefaultResponse(__FUNCTION__, $aResult); return $this->DefaultResponse($aResult);
} }
public function DoClearUserBackground() : array public function DoClearUserBackground() : array
@ -283,7 +282,7 @@ trait User
$oAccount = $this->getAccountFromToken(); $oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(Capa::USER_BACKGROUND)) { if (!$this->GetCapa(Capa::USER_BACKGROUND)) {
return $this->FalseResponse(__FUNCTION__); return $this->FalseResponse();
} }
$oSettings = $this->SettingsProvider()->Load($oAccount); $oSettings = $this->SettingsProvider()->Load($oAccount);
@ -297,7 +296,7 @@ trait User
$oSettings->SetConf('UserBackgroundHash', ''); $oSettings->SetConf('UserBackgroundHash', '');
} }
return $this->DefaultResponse(__FUNCTION__, $oAccount && $oSettings ? return $this->DefaultResponse($oAccount && $oSettings ?
$this->SettingsProvider()->Save($oAccount, $oSettings) : false); $this->SettingsProvider()->Save($oAccount, $oSettings) : false);
} }

View file

@ -13,7 +13,7 @@ use RainLoop\Exceptions\ClientException;
trait UserAuth trait UserAuth
{ {
/** /**
* @var string * @var bool | null | Account
*/ */
private $oAdditionalAuthAccount = false; private $oAdditionalAuthAccount = false;
private $oMainAuthAccount = false; private $oMainAuthAccount = false;
@ -199,7 +199,7 @@ trait UserAuth
/** /**
* Returns RainLoop\Model\AdditionalAccount when it exists, * Returns RainLoop\Model\AdditionalAccount when it exists,
* else returns RainLoop\Model\Account when it exists, * else returns RainLoop\Model\MainAccount when it exists,
* else null * else null
* *
* @throws \RainLoop\Exceptions\ClientException * @throws \RainLoop\Exceptions\ClientException

View file

@ -14,14 +14,14 @@ class ActionsAdmin extends Actions
if (\is_dir(APP_PRIVATE_DATA . 'cache')) { if (\is_dir(APP_PRIVATE_DATA . 'cache')) {
\MailSo\Base\Utils::RecRmDir(APP_PRIVATE_DATA.'cache'); \MailSo\Base\Utils::RecRmDir(APP_PRIVATE_DATA.'cache');
} }
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoAdminSettingsGet() : array public function DoAdminSettingsGet() : array
{ {
$aConfig = $this->Config()->jsonSerialize(); $aConfig = $this->Config()->jsonSerialize();
unset($aConfig['version']); unset($aConfig['version']);
return $this->DefaultResponse(__FUNCTION__, $aConfig); return $this->DefaultResponse($aConfig);
} }
public function DoAdminSettingsSet() : array public function DoAdminSettingsSet() : array
@ -32,13 +32,13 @@ class ActionsAdmin extends Actions
$oConfig->Set($sSection, $sKey, $mValue); $oConfig->Set($sSection, $sKey, $mValue);
} }
} }
return $this->DefaultResponse(__FUNCTION__, $oConfig->Save()); return $this->DefaultResponse($oConfig->Save());
} }
public function DoAdminSettingsUpdate() : array public function DoAdminSettingsUpdate() : array
{ {
// sleep(3); // sleep(3);
// return $this->DefaultResponse(__FUNCTION__, false); // return $this->DefaultResponse(false);
$this->IsAdminLoggined(); $this->IsAdminLoggined();
@ -96,7 +96,7 @@ class ActionsAdmin extends Actions
$this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool'); $this->setConfigFromParams($oConfig, 'TokenProtection', 'security', 'csrf_protection', 'bool');
$this->setConfigFromParams($oConfig, 'EnabledPlugins', 'plugins', 'enable', 'bool'); $this->setConfigFromParams($oConfig, 'EnabledPlugins', 'plugins', 'enable', 'bool');
return $this->DefaultResponse(__FUNCTION__, $oConfig->Save()); return $this->DefaultResponse($oConfig->Save());
} }
/** /**
@ -125,7 +125,7 @@ class ActionsAdmin extends Actions
$sToken = $this->setAdminAuthToken(); $sToken = $this->setAdminAuthToken();
return $this->DefaultResponse(__FUNCTION__, $sToken ? $this->AppData(true) : false); return $this->DefaultResponse($sToken ? $this->AppData(true) : false);
} }
public function DoAdminLogout() : array public function DoAdminLogout() : array
@ -135,7 +135,7 @@ class ActionsAdmin extends Actions
$this->Cacher(null, true)->Delete(KeyPathHelper::SessionAdminKey($sAdminKey)); $this->Cacher(null, true)->Delete(KeyPathHelper::SessionAdminKey($sAdminKey));
} }
Utils::ClearCookie(static::$AUTH_ADMIN_TOKEN_KEY); Utils::ClearCookie(static::$AUTH_ADMIN_TOKEN_KEY);
return $this->TrueResponse(__FUNCTION__); return $this->TrueResponse();
} }
public function DoAdminContactsTest() : array public function DoAdminContactsTest() : array
@ -154,7 +154,7 @@ class ActionsAdmin extends Actions
}); });
$sTestMessage = $this->AddressBookProvider(null, true)->Test(); $sTestMessage = $this->AddressBookProvider(null, true)->Test();
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'Result' => '' === $sTestMessage, 'Result' => '' === $sTestMessage,
'Message' => \MailSo\Base\Utils::Utf8Clear($sTestMessage) 'Message' => \MailSo\Base\Utils::Utf8Clear($sTestMessage)
)); ));
@ -195,7 +195,7 @@ class ActionsAdmin extends Actions
$bResult = $oConfig->Save(); $bResult = $oConfig->Save();
} }
return $this->DefaultResponse(__FUNCTION__, $bResult return $this->DefaultResponse($bResult
? array('Weak' => \is_file($passfile)) ? array('Weak' => \is_file($passfile))
: false); : false);
} }
@ -204,30 +204,28 @@ class ActionsAdmin extends Actions
{ {
$this->IsAdminLoggined(); $this->IsAdminLoggined();
return $this->DefaultResponse(__FUNCTION__, return $this->DefaultResponse($this->DomainProvider()->Load($this->GetActionParam('Name', ''), false, false));
$this->DomainProvider()->Load($this->GetActionParam('Name', ''), false, false));
} }
public function DoAdminDomainList() : array public function DoAdminDomainList() : array
{ {
$this->IsAdminLoggined(); $this->IsAdminLoggined();
$bIncludeAliases = !empty($this->GetActionParam('IncludeAliases', '1')); $bIncludeAliases = !empty($this->GetActionParam('IncludeAliases', '1'));
return $this->DefaultResponse(__FUNCTION__, $this->DomainProvider()->GetList($bIncludeAliases)); return $this->DefaultResponse($this->DomainProvider()->GetList($bIncludeAliases));
} }
public function DoAdminDomainDelete() : array public function DoAdminDomainDelete() : array
{ {
$this->IsAdminLoggined(); $this->IsAdminLoggined();
return $this->DefaultResponse(__FUNCTION__, return $this->DefaultResponse($this->DomainProvider()->Delete((string) $this->GetActionParam('Name', '')));
$this->DomainProvider()->Delete((string) $this->GetActionParam('Name', '')));
} }
public function DoAdminDomainDisable() : array public function DoAdminDomainDisable() : array
{ {
$this->IsAdminLoggined(); $this->IsAdminLoggined();
return $this->DefaultResponse(__FUNCTION__, $this->DomainProvider()->Disable( return $this->DefaultResponse($this->DomainProvider()->Disable(
(string) $this->GetActionParam('Name', ''), (string) $this->GetActionParam('Name', ''),
'1' === (string) $this->GetActionParam('Disabled', '0') '1' === (string) $this->GetActionParam('Disabled', '0')
)); ));
@ -239,15 +237,14 @@ class ActionsAdmin extends Actions
$oDomain = $this->DomainProvider()->LoadOrCreateNewFromAction($this); $oDomain = $this->DomainProvider()->LoadOrCreateNewFromAction($this);
return $this->DefaultResponse(__FUNCTION__, return $this->DefaultResponse($oDomain ? $this->DomainProvider()->Save($oDomain) : false);
$oDomain ? $this->DomainProvider()->Save($oDomain) : false);
} }
public function DoAdminDomainAliasSave() : array public function DoAdminDomainAliasSave() : array
{ {
$this->IsAdminLoggined(); $this->IsAdminLoggined();
return $this->DefaultResponse(__FUNCTION__, $this->DomainProvider()->SaveAlias( return $this->DefaultResponse($this->DomainProvider()->SaveAlias(
(string) $this->GetActionParam('Name', ''), (string) $this->GetActionParam('Name', ''),
(string) $this->GetActionParam('Alias', '') (string) $this->GetActionParam('Alias', '')
)); ));
@ -262,7 +259,7 @@ class ActionsAdmin extends Actions
$oDomain = \str_contains($sEmail, '@') $oDomain = \str_contains($sEmail, '@')
? $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true) ? $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true)
: null; : null;
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'email' => $sEmail, 'email' => $sEmail,
'login' => $sLogin, 'login' => $sLogin,
'domain' => $oDomain, 'domain' => $oDomain,
@ -401,7 +398,7 @@ class ActionsAdmin extends Actions
} }
} }
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'Imap' => $bImapResult ? true : $sImapErrorDesc, 'Imap' => $bImapResult ? true : $sImapErrorDesc,
'Smtp' => $bSmtpResult ? true : $sSmtpErrorDesc, 'Smtp' => $bSmtpResult ? true : $sSmtpErrorDesc,
'Sieve' => $bSieveResult ? true : $sSieveErrorDesc 'Sieve' => $bSieveResult ? true : $sSieveErrorDesc
@ -434,12 +431,12 @@ class ActionsAdmin extends Actions
'loaded' => \class_exists('PharData'), 'loaded' => \class_exists('PharData'),
'version' => \phpversion('phar') 'version' => \phpversion('phar')
]; ];
return $this->DefaultResponse(__FUNCTION__, $aResult); return $this->DefaultResponse($aResult);
} }
public function DoAdminPackagesList() : array public function DoAdminPackagesList() : array
{ {
return $this->DefaultResponse(__FUNCTION__, \SnappyMail\Repository::getPackagesList()); return $this->DefaultResponse(\SnappyMail\Repository::getPackagesList());
} }
public function DoAdminPackageDelete() : array public function DoAdminPackageDelete() : array
@ -447,7 +444,7 @@ class ActionsAdmin extends Actions
$sId = $this->GetActionParam('Id', ''); $sId = $this->GetActionParam('Id', '');
$bResult = \SnappyMail\Repository::deletePackage($sId); $bResult = \SnappyMail\Repository::deletePackage($sId);
static::pluginEnable($sId, false); static::pluginEnable($sId, false);
return $this->DefaultResponse(__FUNCTION__, $bResult); return $this->DefaultResponse($bResult);
} }
public function DoAdminPackageInstall() : array public function DoAdminPackageInstall() : array
@ -458,7 +455,7 @@ class ActionsAdmin extends Actions
$this->GetActionParam('Id', ''), $this->GetActionParam('Id', ''),
$this->GetActionParam('File', '') $this->GetActionParam('File', '')
); );
return $this->DefaultResponse(__FUNCTION__, $bResult ? return $this->DefaultResponse($bResult ?
('plugin' !== $sType ? array('Reload' => true) : true) : false); ('plugin' !== $sType ? array('Reload' => true) : true) : false);
} }
@ -517,7 +514,7 @@ class ActionsAdmin extends Actions
$aWarnings[] = 'Can not edit: ' . APP_INDEX_ROOT_PATH . 'index.php'; $aWarnings[] = 'Can not edit: ' . APP_INDEX_ROOT_PATH . 'index.php';
} }
return $this->DefaultResponse(__FUNCTION__, array( return $this->DefaultResponse(array(
'Updatable' => \SnappyMail\Repository::canUpdateCore(), 'Updatable' => \SnappyMail\Repository::canUpdateCore(),
'Warning' => $bShowWarning, 'Warning' => $bShowWarning,
'Version' => $sVersion, 'Version' => $sVersion,
@ -528,7 +525,7 @@ class ActionsAdmin extends Actions
public function DoAdminUpgradeCore() : array public function DoAdminUpgradeCore() : array
{ {
return $this->DefaultResponse(__FUNCTION__, \SnappyMail\Upgrade::core()); return $this->DefaultResponse(\SnappyMail\Upgrade::core());
} }
public function DoAdminPluginDisable() : array public function DoAdminPluginDisable() : array
@ -546,16 +543,16 @@ class ActionsAdmin extends Actions
$sValue = $oPlugin->Supported(); $sValue = $oPlugin->Supported();
if (\strlen($sValue)) if (\strlen($sValue))
{ {
return $this->FalseResponse(__FUNCTION__, Notifications::UnsupportedPluginPackage, $sValue); return $this->FalseResponse(Notifications::UnsupportedPluginPackage, $sValue);
} }
} }
else else
{ {
return $this->FalseResponse(__FUNCTION__, Notifications::InvalidPluginPackage); return $this->FalseResponse(Notifications::InvalidPluginPackage);
} }
} }
return $this->DefaultResponse(__FUNCTION__, $this->pluginEnable($sId, !$bDisable)); return $this->DefaultResponse($this->pluginEnable($sId, !$bDisable));
} }
public function DoAdminPluginLoad() : array public function DoAdminPluginLoad() : array
@ -606,7 +603,7 @@ class ActionsAdmin extends Actions
} }
} }
return $this->DefaultResponse(__FUNCTION__, $mResult); return $this->DefaultResponse($mResult);
} }
public function DoAdminPluginSettingsUpdate() : array public function DoAdminPluginSettingsUpdate() : array
@ -635,7 +632,7 @@ class ActionsAdmin extends Actions
} }
} }
if ($oConfig->Save()) { if ($oConfig->Save()) {
return $this->DefaultResponse(__FUNCTION__, true); return $this->TrueResponse();
} }
} }
} }
@ -653,7 +650,7 @@ class ActionsAdmin extends Actions
// "otpauth://totp/{$user}?secret={$secret}", // "otpauth://totp/{$user}?secret={$secret}",
\SnappyMail\QRCode::ERROR_CORRECT_LEVEL_M \SnappyMail\QRCode::ERROR_CORRECT_LEVEL_M
); );
return $this->DefaultResponse(__FUNCTION__, $QR->__toString()); return $this->DefaultResponse($QR->__toString());
} }
private function setAdminAuthToken() : string private function setAdminAuthToken() : string

View file

@ -70,8 +70,7 @@ class Notifications
static public function GetNotificationsMessage(int $iCode, ?\Throwable $oPrevious = null) : string static public function GetNotificationsMessage(int $iCode, ?\Throwable $oPrevious = null) : string
{ {
if (self::ClientViewError === $iCode && $oPrevious) if (self::ClientViewError === $iCode && $oPrevious) {
{
return $oPrevious->getMessage(); return $oPrevious->getMessage();
} }

View file

@ -25,25 +25,13 @@ abstract class AbstractPlugin
*/ */
private $oPluginConfig = null; private $oPluginConfig = null;
/** private bool $bLangs = false;
* @var bool
*/
private $bLangs = false;
/** private string $sName;
* @var string
*/
private $sName;
/** private string $sPath = '';
* @var string
*/
private $sPath = '';
/** private ?array $aConfigMap = null;
* @var array
*/
private $aConfigMap = null;
public function __construct() public function __construct()
{ {
@ -63,8 +51,7 @@ abstract class AbstractPlugin
public function UseLangs(?bool $bLangs = null) : bool public function UseLangs(?bool $bLangs = null) : bool
{ {
if (null !== $bLangs) if (null !== $bLangs) {
{
$this->bLangs = $bLangs; $this->bLangs = $bLangs;
} }
@ -113,8 +100,7 @@ abstract class AbstractPlugin
final public function ConfigMap(bool $flatten = false) : array final public function ConfigMap(bool $flatten = false) : array
{ {
if (null === $this->aConfigMap) if (null === $this->aConfigMap) {
{
$this->aConfigMap = $this->configMapping(); $this->aConfigMap = $this->configMapping();
} }
@ -163,8 +149,7 @@ abstract class AbstractPlugin
final public function SetPluginConfig(\RainLoop\Config\Plugin $oPluginConfig) : self final public function SetPluginConfig(\RainLoop\Config\Plugin $oPluginConfig) : self
{ {
$this->oPluginConfig = $oPluginConfig; $this->oPluginConfig = $oPluginConfig;
if ($oPluginConfig->IsInited() && !$oPluginConfig->Load()) if ($oPluginConfig->IsInited() && !$oPluginConfig->Load()) {
{
$oPluginConfig->Save(); $oPluginConfig->Save();
} }
return $this; return $this;
@ -172,8 +157,7 @@ abstract class AbstractPlugin
final protected function addHook(string $sHookName, string $sFunctionName) : self final protected function addHook(string $sHookName, string $sFunctionName) : self
{ {
if ($this->oPluginManager) if ($this->oPluginManager) {
{
$this->oPluginManager->AddHook($sHookName, array($this, $sFunctionName)); $this->oPluginManager->AddHook($sHookName, array($this, $sFunctionName));
} }
@ -182,8 +166,7 @@ abstract class AbstractPlugin
final protected function addCss(string $sFile, bool $bAdminScope = false) : self final protected function addCss(string $sFile, bool $bAdminScope = false) : self
{ {
if ($this->oPluginManager) if ($this->oPluginManager) {
{
$this->oPluginManager->AddCss($this->sPath.'/'.$sFile, $bAdminScope); $this->oPluginManager->AddCss($this->sPath.'/'.$sFile, $bAdminScope);
} }
@ -192,8 +175,7 @@ abstract class AbstractPlugin
final protected function addJs(string $sFile, bool $bAdminScope = false) : self final protected function addJs(string $sFile, bool $bAdminScope = false) : self
{ {
if ($this->oPluginManager) if ($this->oPluginManager) {
{
$this->oPluginManager->AddJs($this->sPath.'/'.$sFile, $bAdminScope); $this->oPluginManager->AddJs($this->sPath.'/'.$sFile, $bAdminScope);
} }
@ -202,8 +184,7 @@ abstract class AbstractPlugin
final protected function addTemplate(string $sFile, bool $bAdminScope = false) : self final protected function addTemplate(string $sFile, bool $bAdminScope = false) : self
{ {
if ($this->oPluginManager) if ($this->oPluginManager) {
{
$this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope); $this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope);
} }
@ -212,8 +193,7 @@ abstract class AbstractPlugin
final protected function replaceTemplate(string $sFile, bool $bAdminScope = false) : self final protected function replaceTemplate(string $sFile, bool $bAdminScope = false) : self
{ {
if ($this->oPluginManager) if ($this->oPluginManager) {
{
$this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope); $this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope);
} }
@ -222,8 +202,7 @@ abstract class AbstractPlugin
final protected function addPartHook(string $sActionName, string $sFunctionName) : self final protected function addPartHook(string $sActionName, string $sFunctionName) : self
{ {
if ($this->oPluginManager) if ($this->oPluginManager) {
{
$this->oPluginManager->AddAdditionalPartAction($sActionName, array($this, $sFunctionName)); $this->oPluginManager->AddAdditionalPartAction($sActionName, array($this, $sFunctionName));
} }
@ -232,8 +211,7 @@ abstract class AbstractPlugin
final protected function addJsonHook(string $sActionName, string $sFunctionName) : self final protected function addJsonHook(string $sActionName, string $sFunctionName) : self
{ {
if ($this->oPluginManager) if ($this->oPluginManager) {
{
$this->oPluginManager->AddAdditionalJsonAction($sActionName, array($this, $sFunctionName)); $this->oPluginManager->AddAdditionalJsonAction($sActionName, array($this, $sFunctionName));
} }

View file

@ -101,10 +101,8 @@ class Manager
$aList = array(); $aList = array();
$aGlob = \glob(APP_PLUGINS_PATH.'*'); $aGlob = \glob(APP_PLUGINS_PATH.'*');
if (\is_array($aGlob)) if (\is_array($aGlob)) {
{ foreach ($aGlob as $sPathName) {
foreach ($aGlob as $sPathName)
{
if (\is_dir($sPathName)) { if (\is_dir($sPathName)) {
$sName = \basename($sPathName); $sName = \basename($sPathName);
} else if ('.phar' === \substr($sPathName, -5)) { } else if ('.phar' === \substr($sPathName, -5)) {
@ -122,9 +120,7 @@ class Manager
); );
} }
} }
} } else {
else
{
$this->oActions->Logger()->Write('Cannot get installed plugins from '.APP_PLUGINS_PATH, $this->oActions->Logger()->Write('Cannot get installed plugins from '.APP_PLUGINS_PATH,
\LOG_ERR); \LOG_ERR);
} }
@ -222,13 +218,10 @@ class Manager
public function CompileTemplate(array &$aList, bool $bAdminScope = false) : void public function CompileTemplate(array &$aList, bool $bAdminScope = false) : void
{ {
if ($this->bIsEnabled) if ($this->bIsEnabled) {
{
$aTemplates = $bAdminScope ? $this->aAdminTemplates : $this->aTemplates; $aTemplates = $bAdminScope ? $this->aAdminTemplates : $this->aTemplates;
foreach ($aTemplates as $sFile) foreach ($aTemplates as $sFile) {
{ if (\is_readable($sFile)) {
if (\is_readable($sFile))
{
$sTemplateName = \substr(\basename($sFile), 0, -5); $sTemplateName = \substr(\basename($sFile), 0, -5);
$aList[$sTemplateName] = $sFile; $aList[$sTemplateName] = $sFile;
} }
@ -238,21 +231,15 @@ class Manager
public function InitAppData(bool $bAdmin, array &$aAppData, ?\RainLoop\Model\Account $oAccount = null) : self public function InitAppData(bool $bAdmin, array &$aAppData, ?\RainLoop\Model\Account $oAccount = null) : self
{ {
if ($this->bIsEnabled && isset($aAppData['Plugins']) && \is_array($aAppData['Plugins'])) if ($this->bIsEnabled && isset($aAppData['Plugins']) && \is_array($aAppData['Plugins'])) {
{
$bAuth = !empty($aAppData['Auth']); $bAuth = !empty($aAppData['Auth']);
foreach ($this->aPlugins as $oPlugin) foreach ($this->aPlugins as $oPlugin) {
{ if ($oPlugin) {
if ($oPlugin)
{
$aConfig = array(); $aConfig = array();
$aMap = $oPlugin->ConfigMap(true); $aMap = $oPlugin->ConfigMap(true);
if (\is_array($aMap)) if (\is_array($aMap)) {
{ foreach ($aMap as /* @var $oPluginProperty \RainLoop\Plugins\Property */ $oPluginProperty) {
foreach ($aMap as /* @var $oPluginProperty \RainLoop\Plugins\Property */ $oPluginProperty) if ($oPluginProperty && $oPluginProperty->AllowedInJs()) {
{
if ($oPluginProperty && $oPluginProperty->AllowedInJs())
{
$aConfig[$oPluginProperty->Name()] = $aConfig[$oPluginProperty->Name()] =
$oPlugin->Config()->Get('plugin', $oPlugin->Config()->Get('plugin',
$oPluginProperty->Name(), $oPluginProperty->Name(),
@ -263,8 +250,7 @@ class Manager
$oPlugin->FilterAppDataPluginSection($bAdmin, $bAuth, $aConfig); $oPlugin->FilterAppDataPluginSection($bAdmin, $bAuth, $aConfig);
if (\count($aConfig)) if (\count($aConfig)) {
{
$aAppData['Plugins'][$oPlugin->Name()] = $aConfig; $aAppData['Plugins'][$oPlugin->Name()] = $aConfig;
} }
} }
@ -310,14 +296,10 @@ class Manager
public function AddTemplate(string $sFile, bool $bAdminScope = false) : self public function AddTemplate(string $sFile, bool $bAdminScope = false) : self
{ {
if ($this->bIsEnabled) if ($this->bIsEnabled) {
{ if ($bAdminScope) {
if ($bAdminScope)
{
$this->aAdminTemplates[$sFile] = $sFile; $this->aAdminTemplates[$sFile] = $sFile;
} } else {
else
{
$this->aTemplates[$sFile] = $sFile; $this->aTemplates[$sFile] = $sFile;
} }
} }
@ -346,11 +328,9 @@ class Manager
*/ */
public function AddAdditionalPartAction(string $sActionName, $mCallbak) : self public function AddAdditionalPartAction(string $sActionName, $mCallbak) : self
{ {
if ($this->bIsEnabled && \is_callable($mCallbak)) if ($this->bIsEnabled && \is_callable($mCallbak)) {
{
$sActionName = \strtolower($sActionName); $sActionName = \strtolower($sActionName);
if (!isset($this->aAdditionalParts[$sActionName])) if (!isset($this->aAdditionalParts[$sActionName])) {
{
$this->aAdditionalParts[$sActionName] = array(); $this->aAdditionalParts[$sActionName] = array();
} }
@ -363,13 +343,10 @@ class Manager
public function RunAdditionalPart(string $sActionName, array $aParts = array()) : bool public function RunAdditionalPart(string $sActionName, array $aParts = array()) : bool
{ {
$bResult = false; $bResult = false;
if ($this->bIsEnabled) if ($this->bIsEnabled) {
{
$sActionName = \strtolower($sActionName); $sActionName = \strtolower($sActionName);
if (isset($this->aAdditionalParts[$sActionName])) if (isset($this->aAdditionalParts[$sActionName])) {
{ foreach ($this->aAdditionalParts[$sActionName] as $mCallbak) {
foreach ($this->aAdditionalParts[$sActionName] as $mCallbak)
{
$bResult = !!$mCallbak(...$aParts) || $bResult; $bResult = !!$mCallbak(...$aParts) || $bResult;
} }
} }
@ -405,20 +382,17 @@ class Manager
*/ */
public function JsonResponseHelper(string $sFunctionName, $mData) : array public function JsonResponseHelper(string $sFunctionName, $mData) : array
{ {
return $this->oActions->DefaultResponse($sFunctionName, $mData); return $this->oActions->DefaultResponse($mData, [], $sFunctionName);
} }
public function GetUserPluginSettings(string $sPluginName) : array public function GetUserPluginSettings(string $sPluginName) : array
{ {
$oAccount = $this->oActions->GetAccount(); $oAccount = $this->oActions->GetAccount();
if ($oAccount) if ($oAccount) {
{
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount); $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
if ($oSettings) if ($oSettings) {
{
$aData = $oSettings->GetConf('Plugins', array()); $aData = $oSettings->GetConf('Plugins', array());
if (isset($aData[$sPluginName]) && \is_array($aData[$sPluginName])) if (isset($aData[$sPluginName]) && \is_array($aData[$sPluginName])) {
{
return $aData[$sPluginName]; return $aData[$sPluginName];
} }
} }
@ -430,25 +404,20 @@ class Manager
public function SaveUserPluginSettings(string $sPluginName, array $aSettings) : bool public function SaveUserPluginSettings(string $sPluginName, array $aSettings) : bool
{ {
$oAccount = $this->oActions->GetAccount(); $oAccount = $this->oActions->GetAccount();
if ($oAccount) if ($oAccount) {
{
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount); $oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
if ($oSettings) if ($oSettings) {
{
$aData = $oSettings->GetConf('Plugins', array()); $aData = $oSettings->GetConf('Plugins', array());
if (!\is_array($aData)) if (!\is_array($aData)) {
{
$aData = array(); $aData = array();
} }
$aPluginSettings = array(); $aPluginSettings = array();
if (isset($aData[$sPluginName]) && \is_array($aData[$sPluginName])) if (isset($aData[$sPluginName]) && \is_array($aData[$sPluginName])) {
{
$aPluginSettings = $aData[$sPluginName]; $aPluginSettings = $aData[$sPluginName];
} }
foreach ($aSettings as $sKey => $mValue) foreach ($aSettings as $sKey => $mValue) {
{
$aPluginSettings[$sKey] = $mValue; $aPluginSettings[$sKey] = $mValue;
} }
@ -518,16 +487,14 @@ class Manager
public function WriteLog(string $sDesc, int $iType = \LOG_INFO) : void public function WriteLog(string $sDesc, int $iType = \LOG_INFO) : void
{ {
if ($this->oLogger) if ($this->oLogger) {
{
$this->oLogger->Write($sDesc, $iType, 'PLUGIN'); $this->oLogger->Write($sDesc, $iType, 'PLUGIN');
} }
} }
public function WriteException(string $sDesc, int $iType = \LOG_INFO) : void public function WriteException(string $sDesc, int $iType = \LOG_INFO) : void
{ {
if ($this->oLogger) if ($this->oLogger) {
{
$this->oLogger->WriteException($sDesc, $iType, 'PLUGIN'); $this->oLogger->WriteException($sDesc, $iType, 'PLUGIN');
} }
} }

View file

@ -10,8 +10,7 @@ abstract class Service
public static function Handle() : bool public static function Handle() : bool
{ {
static $bOne = null; static $bOne = null;
if (null === $bOne) if (null === $bOne) {
{
$bOne = static::RunResult(); $bOne = static::RunResult();
} }
@ -23,8 +22,7 @@ abstract class Service
$oConfig = Api::Config(); $oConfig = Api::Config();
$sServer = \trim($oConfig->Get('security', 'custom_server_signature', '')); $sServer = \trim($oConfig->Get('security', 'custom_server_signature', ''));
if (\strlen($sServer)) if (\strlen($sServer)) {
{
\header('Server: '.$sServer); \header('Server: '.$sServer);
} }
@ -40,8 +38,7 @@ abstract class Service
\header('X-XSS-Protection: '.$sXssProtectionOptionsHeader); \header('X-XSS-Protection: '.$sXssProtectionOptionsHeader);
$oHttp = \MailSo\Base\Http::SingletonInstance(); $oHttp = \MailSo\Base\Http::SingletonInstance();
if ($oConfig->Get('labs', 'force_https', false) && !$oHttp->IsSecure()) if ($oConfig->Get('labs', 'force_https', false) && !$oHttp->IsSecure()) {
{
\header('Location: https://'.$oHttp->GetHost(false, false).$oHttp->GetUrl()); \header('Location: https://'.$oHttp->GetHost(false, false).$oHttp->GetUrl());
exit; exit;
} }
@ -67,13 +64,10 @@ abstract class Service
$bAdmin = false; $bAdmin = false;
$sAdminPanelHost = $oConfig->Get('security', 'admin_panel_host', ''); $sAdminPanelHost = $oConfig->Get('security', 'admin_panel_host', '');
if (empty($sAdminPanelHost)) if (empty($sAdminPanelHost)) {
{
$bAdmin = !empty($aPaths[0]) && ($oConfig->Get('security', 'admin_panel_key', '') ?: 'admin') === $aPaths[0]; $bAdmin = !empty($aPaths[0]) && ($oConfig->Get('security', 'admin_panel_key', '') ?: 'admin') === $aPaths[0];
$bAdmin && \array_shift($aPaths); $bAdmin && \array_shift($aPaths);
} } else if (empty($aPaths[0]) && \mb_strtolower($sAdminPanelHost) === \mb_strtolower($oHttp->GetHost())) {
else if (empty($aPaths[0]) && \mb_strtolower($sAdminPanelHost) === \mb_strtolower($oHttp->GetHost()))
{
$bAdmin = true; $bAdmin = true;
} }
@ -81,15 +75,13 @@ abstract class Service
$oActions->Plugins()->RunHook('filter.http-paths', array(&$aPaths)); $oActions->Plugins()->RunHook('filter.http-paths', array(&$aPaths));
if ($oHttp->IsPost()) if ($oHttp->IsPost()) {
{
$oHttp->ServerNoCache(); $oHttp->ServerNoCache();
} }
$oServiceActions = new ServiceActions($oHttp, $oActions); $oServiceActions = new ServiceActions($oHttp, $oActions);
if ($bAdmin && !$oConfig->Get('security', 'allow_admin_panel', true)) if ($bAdmin && !$oConfig->Get('security', 'allow_admin_panel', true)) {
{
\MailSo\Base\Http::StatusHeader(403); \MailSo\Base\Http::StatusHeader(403);
echo $oServiceActions->ErrorTemplates('Access Denied.', echo $oServiceActions->ErrorTemplates('Access Denied.',
'Access to the SnappyMail Admin Panel is not allowed!'); 'Access to the SnappyMail Admin Panel is not allowed!');
@ -99,8 +91,7 @@ abstract class Service
$bIndex = true; $bIndex = true;
$sResult = ''; $sResult = '';
if (\count($aPaths) && !empty($aPaths[0]) && 'index' !== \strtolower($aPaths[0])) if (\count($aPaths) && !empty($aPaths[0]) && 'index' !== \strtolower($aPaths[0])) {
{
if ('mailto' !== \strtolower($aPaths[0]) && !\SnappyMail\HTTP\SecFetch::matchAnyRule($oConfig->Get('security', 'secfetch_allow', ''))) { if ('mailto' !== \strtolower($aPaths[0]) && !\SnappyMail\HTTP\SecFetch::matchAnyRule($oConfig->Get('security', 'secfetch_allow', ''))) {
\MailSo\Base\Http::StatusHeader(403); \MailSo\Base\Http::StatusHeader(403);
echo $oServiceActions->ErrorTemplates('Access Denied.', echo $oServiceActions->ErrorTemplates('Access Denied.',
@ -116,20 +107,15 @@ abstract class Service
$sMethodName = 'Service'.\preg_replace('/@.+$/', '', $aPaths[0]); $sMethodName = 'Service'.\preg_replace('/@.+$/', '', $aPaths[0]);
$sMethodExtra = \strpos($aPaths[0], '@') ? \preg_replace('/^[^@]+@/', '', $aPaths[0]) : ''; $sMethodExtra = \strpos($aPaths[0], '@') ? \preg_replace('/^[^@]+@/', '', $aPaths[0]) : '';
if (\method_exists($oServiceActions, $sMethodName) && if (\method_exists($oServiceActions, $sMethodName) && \is_callable(array($oServiceActions, $sMethodName))) {
\is_callable(array($oServiceActions, $sMethodName)))
{
$oServiceActions->SetQuery($sQuery)->SetPaths($aPaths); $oServiceActions->SetQuery($sQuery)->SetPaths($aPaths);
$sResult = $oServiceActions->{$sMethodName}($sMethodExtra); $sResult = $oServiceActions->{$sMethodName}($sMethodExtra);
} } else if (!$oActions->Plugins()->RunAdditionalPart($aPaths[0], $aPaths)) {
else if (!$oActions->Plugins()->RunAdditionalPart($aPaths[0], $aPaths))
{
$bIndex = true; $bIndex = true;
} }
} }
if ($bIndex) if ($bIndex) {
{
if (!$bAdmin) { if (!$bAdmin) {
$login = $oConfig->Get('labs', 'custom_login_link', ''); $login = $oConfig->Get('labs', 'custom_login_link', '');
if ($login && !$oActions->getAccountFromToken(false)) { if ($login && !$oActions->getAccountFromToken(false)) {
@ -142,8 +128,7 @@ abstract class Service
\header('Content-Type: text/html; charset=utf-8'); \header('Content-Type: text/html; charset=utf-8');
$oHttp->ServerNoCache(); $oHttp->ServerNoCache();
if (!\is_dir(APP_DATA_FOLDER_PATH) || !\is_writable(APP_DATA_FOLDER_PATH)) if (!\is_dir(APP_DATA_FOLDER_PATH) || !\is_writable(APP_DATA_FOLDER_PATH)) {
{
echo $oServiceActions->ErrorTemplates( echo $oServiceActions->ErrorTemplates(
'Permission denied!', 'Permission denied!',
'SnappyMail can not access the data folder "'.APP_DATA_FOLDER_PATH.'"' 'SnappyMail can not access the data folder "'.APP_DATA_FOLDER_PATH.'"'
@ -175,8 +160,7 @@ abstract class Service
); );
$sCacheFileName = ''; $sCacheFileName = '';
if ($oConfig->Get('labs', 'cache_system_data', true)) if ($oConfig->Get('labs', 'cache_system_data', true)) {
{
$sCacheFileName = 'TMPL:' . $sLanguage . \md5( $sCacheFileName = 'TMPL:' . $sLanguage . \md5(
Utils::jsonEncode(array( Utils::jsonEncode(array(
$oConfig->Get('cache', 'index', ''), $oConfig->Get('cache', 'index', ''),
@ -217,9 +201,7 @@ abstract class Service
$sScriptHash = 'sha256-'.\base64_encode(\hash('sha256', $script[1], true)); $sScriptHash = 'sha256-'.\base64_encode(\hash('sha256', $script[1], true));
static::setCSP(null, $sScriptHash); static::setCSP(null, $sScriptHash);
*/ */
} } else if (!\headers_sent()) {
else if (!\headers_sent())
{
\header('X-XSS-Protection: 1; mode=block'); \header('X-XSS-Protection: 1; mode=block');
} }

View file

@ -4,32 +4,18 @@ namespace RainLoop;
class ServiceActions class ServiceActions
{ {
/** protected \MailSo\Base\Http $oHttp;
* @var \MailSo\Base\Http
*/
protected $oHttp;
/** protected Actions $oActions;
* @var \RainLoop\Actions
*/
protected $oActions;
/** protected array $aPaths = array();
* @var array
*/
protected $aPaths;
/** protected string $sQuery = '';
* @var string
*/
protected $sQuery;
public function __construct(\MailSo\Base\Http $oHttp, Actions $oActions) public function __construct(\MailSo\Base\Http $oHttp, Actions $oActions)
{ {
$this->oHttp = $oHttp; $this->oHttp = $oHttp;
$this->oActions = $oActions; $this->oActions = $oActions;
$this->aPaths = array();
$this->sQuery = '';
} }
private function Logger() : \MailSo\Log\Logger private function Logger() : \MailSo\Log\Logger
@ -94,8 +80,7 @@ class ServiceActions
$_POST = \json_decode(\file_get_contents('php://input'), true); $_POST = \json_decode(\file_get_contents('php://input'), true);
$sAction = $_POST['Action'] ?? ''; $sAction = $_POST['Action'] ?? '';
if (empty($sAction) && $this->oHttp->IsGet() && !empty($this->aPaths[2])) if (empty($sAction) && $this->oHttp->IsGet() && !empty($this->aPaths[2])) {
{
$sAction = $this->aPaths[2]; $sAction = $this->aPaths[2];
} }
@ -103,14 +88,17 @@ class ServiceActions
try try
{ {
if (empty($sAction)) {
throw new Exceptions\ClientException(Notifications::InvalidInputArgument, null, 'Action unknown');
}
if ($this->oHttp->IsPost() && if ($this->oHttp->IsPost() &&
$this->Config()->Get('security', 'csrf_protection', false) && $this->Config()->Get('security', 'csrf_protection', false) &&
($_POST['XToken'] ?? '') !== Utils::GetCsrfToken()) ($_POST['XToken'] ?? '') !== Utils::GetCsrfToken())
{ {
throw new Exceptions\ClientException(Notifications::InvalidToken, null, 'CSRF failed'); throw new Exceptions\ClientException(Notifications::InvalidToken, null, 'CSRF failed');
} }
if (!empty($sAction))
{
if ($this->oActions instanceof ActionsAdmin && 0 === \stripos($sAction, 'Admin') && !\in_array($sAction, ['AdminLogin', 'AdminLogout'])) { if ($this->oActions instanceof ActionsAdmin && 0 === \stripos($sAction, 'Admin') && !\in_array($sAction, ['AdminLogin', 'AdminLogout'])) {
$this->oActions->IsAdminLoggined(); $this->oActions->IsAdminLoggined();
} }
@ -120,8 +108,7 @@ class ServiceActions
$this->Logger()->Write('Action: '.$sMethodName, \LOG_INFO, 'JSON'); $this->Logger()->Write('Action: '.$sMethodName, \LOG_INFO, 'JSON');
$aPost = $_POST ?? null; $aPost = $_POST ?? null;
if ($aPost) if ($aPost) {
{
$this->oActions->SetActionParams($aPost, $sMethodName); $this->oActions->SetActionParams($aPost, $sMethodName);
foreach ($aPost as $key => $value) { foreach ($aPost as $key => $value) {
if (false !== \stripos($key, 'Password')) { if (false !== \stripos($key, 'Password')) {
@ -138,31 +125,24 @@ class ServiceActions
break; break;
} }
*/ */
$this->Logger()->Write(Utils::jsonEncode($aPost), $this->Logger()->Write(Utils::jsonEncode($aPost), \LOG_INFO, 'POST', true);
\LOG_INFO, 'POST', true); } else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) {
}
else if (3 < \count($this->aPaths) && $this->oHttp->IsGet())
{
$this->oActions->SetActionParams(array( $this->oActions->SetActionParams(array(
'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3]
), $sMethodName); ), $sMethodName);
} }
if (\method_exists($this->oActions, $sMethodName) && if (\method_exists($this->oActions, $sMethodName) && \is_callable(array($this->oActions, $sMethodName))) {
\is_callable(array($this->oActions, $sMethodName))) $this->Plugins()->RunHook("json.before-{$sAction}");
{
$sAction && $this->Plugins()->RunHook("json.before-{$sAction}");
$aResponse = $this->oActions->{$sMethodName}(); $aResponse = $this->oActions->{$sMethodName}();
} } else if ($this->Plugins()->HasAdditionalJson($sMethodName)) {
else if ($this->Plugins()->HasAdditionalJson($sMethodName)) $this->Plugins()->RunHook("json.before-{$sAction}");
{
$sAction && $this->Plugins()->RunHook("json.before-{$sAction}");
$aResponse = $this->Plugins()->RunAdditionalJson($sMethodName); $aResponse = $this->Plugins()->RunAdditionalJson($sMethodName);
} }
if ($sAction && \is_array($aResponse)) {
if (\is_array($aResponse)) {
$this->Plugins()->RunHook("json.after-{$sAction}", array(&$aResponse)); $this->Plugins()->RunHook("json.after-{$sAction}", array(&$aResponse));
} }
}
if (!\is_array($aResponse)) { if (!\is_array($aResponse)) {
throw new Exceptions\ClientException(Notifications::UnknownError); throw new Exceptions\ClientException(Notifications::UnknownError);
@ -175,10 +155,11 @@ class ServiceActions
\SnappyMail\Log::warning('SERVICE', "- {$e->getMessage()} @ {$e->getFile()}#{$e->getLine()}"); \SnappyMail\Log::warning('SERVICE', "- {$e->getMessage()} @ {$e->getFile()}#{$e->getLine()}");
} }
$aResponse = $this->oActions->ExceptionResponse( $aResponse = $this->oActions->ExceptionResponse($oException);
empty($sAction) ? 'Unknown' : $sAction, $oException);
} }
$aResponse['Action'] = $sAction ?: 'Unknown';
if (\is_array($aResponse)) { if (\is_array($aResponse)) {
$aResponse['Time'] = (int) ((\microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000); $aResponse['Time'] = (int) ((\microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000);
} }
@ -191,15 +172,12 @@ class ServiceActions
$sObResult = \ob_get_clean(); $sObResult = \ob_get_clean();
if ($this->Logger()->IsEnabled()) if ($this->Logger()->IsEnabled()) {
{ if (\strlen($sObResult)) {
if (\strlen($sObResult))
{
$this->Logger()->Write($sObResult, \LOG_ERR, 'OB-DATA'); $this->Logger()->Write($sObResult, \LOG_ERR, 'OB-DATA');
} }
if ($oException) if ($oException) {
{
$this->Logger()->WriteException($oException, \LOG_ERR); $this->Logger()->WriteException($oException, \LOG_ERR);
} }
@ -218,9 +196,7 @@ class ServiceActions
$oException = null; $oException = null;
try try
{ {
if (\method_exists($this->oActions, 'Append') && if (\method_exists($this->oActions, 'Append') && \is_callable(array($this->oActions, 'Append'))) {
\is_callable(array($this->oActions, 'Append')))
{
isset($_POST) && $this->oActions->SetActionParams($_POST, 'Append'); isset($_POST) && $this->oActions->SetActionParams($_POST, 'Append');
$bResponse = $this->oActions->Append(); $bResponse = $this->oActions->Append();
} }
@ -234,13 +210,11 @@ class ServiceActions
$sResult = true === $bResponse ? '1' : '0'; $sResult = true === $bResponse ? '1' : '0';
$sObResult = \ob_get_clean(); $sObResult = \ob_get_clean();
if (\strlen($sObResult)) if (\strlen($sObResult)) {
{
$this->Logger()->Write($sObResult, \LOG_ERR, 'OB-DATA'); $this->Logger()->Write($sObResult, \LOG_ERR, 'OB-DATA');
} }
if ($oException) if ($oException) {
{
$this->Logger()->WriteException($oException, \LOG_ERR); $this->Logger()->WriteException($oException, \LOG_ERR);
} }
@ -264,33 +238,24 @@ class ServiceActions
$iError = UPLOAD_ERR_OK; $iError = UPLOAD_ERR_OK;
$_FILES = isset($_FILES) ? $_FILES : null; $_FILES = isset($_FILES) ? $_FILES : null;
if (isset($_FILES[$sInputName], $_FILES[$sInputName]['name'], $_FILES[$sInputName]['tmp_name'], $_FILES[$sInputName]['size'])) if (isset($_FILES[$sInputName], $_FILES[$sInputName]['name'], $_FILES[$sInputName]['tmp_name'], $_FILES[$sInputName]['size'])) {
{
$iError = (isset($_FILES[$sInputName]['error'])) ? (int) $_FILES[$sInputName]['error'] : UPLOAD_ERR_OK; $iError = (isset($_FILES[$sInputName]['error'])) ? (int) $_FILES[$sInputName]['error'] : UPLOAD_ERR_OK;
// \is_uploaded_file($_FILES[$sInputName]['tmp_name']) // \is_uploaded_file($_FILES[$sInputName]['tmp_name'])
if (UPLOAD_ERR_OK === $iError && 0 < $iSizeLimit && $iSizeLimit < (int) $_FILES[$sInputName]['size']) if (UPLOAD_ERR_OK === $iError && 0 < $iSizeLimit && $iSizeLimit < (int) $_FILES[$sInputName]['size']) {
{
$iError = Enumerations\UploadError::CONFIG_SIZE; $iError = Enumerations\UploadError::CONFIG_SIZE;
} }
if (UPLOAD_ERR_OK === $iError) if (UPLOAD_ERR_OK === $iError) {
{
$aFile = $_FILES[$sInputName]; $aFile = $_FILES[$sInputName];
} }
} } else if (empty($_FILES)) {
else if (empty($_FILES))
{
$iError = UPLOAD_ERR_INI_SIZE; $iError = UPLOAD_ERR_INI_SIZE;
} } else {
else
{
$iError = Enumerations\UploadError::EMPTY_FILES_DATA; $iError = Enumerations\UploadError::EMPTY_FILES_DATA;
} }
if (\method_exists($this->oActions, $sAction) && if (\method_exists($this->oActions, $sAction) && \is_callable(array($this->oActions, $sAction))) {
\is_callable(array($this->oActions, $sAction)))
{
$aActionParams = isset($_GET) && \is_array($_GET) ? $_GET : null; $aActionParams = isset($_GET) && \is_array($_GET) ? $_GET : null;
$aActionParams['File'] = $aFile; $aActionParams['File'] = $aFile;
@ -309,9 +274,11 @@ class ServiceActions
} }
catch (\Throwable $oException) catch (\Throwable $oException)
{ {
$aResponse = $this->oActions->ExceptionResponse($sAction, $oException); $aResponse = $this->oActions->ExceptionResponse($oException);
} }
$aResponse['Action'] = $sAction ?: 'Unknown';
\header('Content-Type: application/json; charset=utf-8'); \header('Content-Type: application/json; charset=utf-8');
$sResult = Utils::jsonEncode($aResponse); $sResult = Utils::jsonEncode($aResponse);
@ -392,12 +359,10 @@ class ServiceActions
try try
{ {
$sRawError = 'Invalid action'; $sRawError = 'Invalid action';
if (\strlen($sAction)) if (\strlen($sAction)) {
{
try { try {
$sMethodName = 'Raw'.$sAction; $sMethodName = 'Raw'.$sAction;
if (\method_exists($this->oActions, $sMethodName)) if (\method_exists($this->oActions, $sMethodName)) {
{
\header('X-Raw-Action: '.$sMethodName); \header('X-Raw-Action: '.$sMethodName);
\header('Content-Security-Policy: script-src \'none\'; child-src \'none\''); \header('Content-Security-Policy: script-src \'none\'; child-src \'none\'');
@ -407,22 +372,17 @@ class ServiceActions
'Params' => $this->aPaths 'Params' => $this->aPaths
), $sMethodName); ), $sMethodName);
if (!$this->oActions->{$sMethodName}()) if (!$this->oActions->{$sMethodName}()) {
{
$sRawError = 'False result'; $sRawError = 'False result';
} }
} } else {
else
{
$sRawError = 'Unknown action "'.$sAction.'"'; $sRawError = 'Unknown action "'.$sAction.'"';
} }
} catch (\Throwable $e) { } catch (\Throwable $e) {
// error_log(print_r($e,1)); // error_log(print_r($e,1));
$sRawError = $e->getMessage(); $sRawError = $e->getMessage();
} }
} } else {
else
{
$sRawError = 'Empty action'; $sRawError = 'Empty action';
} }
} }
@ -437,14 +397,12 @@ class ServiceActions
$sRawError = 'Exception as result'; $sRawError = 'Exception as result';
} }
if (\strlen($sRawError)) if (\strlen($sRawError)) {
{
$this->Logger()->Write($sRawError, \LOG_ERR); $this->Logger()->Write($sRawError, \LOG_ERR);
$this->Logger()->WriteDump($this->aPaths, \LOG_ERR, 'PATHS'); $this->Logger()->WriteDump($this->aPaths, \LOG_ERR, 'PATHS');
} }
if ($oException) if ($oException) {
{
$this->Logger()->WriteException($oException, \LOG_ERR, 'RAW'); $this->Logger()->WriteException($oException, \LOG_ERR, 'RAW');
} }
@ -457,37 +415,31 @@ class ServiceActions
$sResult = ''; $sResult = '';
\header('Content-Type: application/javascript; charset=utf-8'); \header('Content-Type: application/javascript; charset=utf-8');
if (!empty($this->aPaths[3])) if (!empty($this->aPaths[3])) {
{
$bAdmin = 'Admin' === (isset($this->aPaths[2]) ? (string) $this->aPaths[2] : 'App'); $bAdmin = 'Admin' === (isset($this->aPaths[2]) ? (string) $this->aPaths[2] : 'App');
$sLanguage = $this->oActions->ValidateLanguage($this->aPaths[3], '', $bAdmin); $sLanguage = $this->oActions->ValidateLanguage($this->aPaths[3], '', $bAdmin);
$bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true);
if (!empty($sLanguage) && $bCacheEnabled) if (!empty($sLanguage) && $bCacheEnabled) {
{
$this->oActions->verifyCacheByKey($this->sQuery); $this->oActions->verifyCacheByKey($this->sQuery);
} }
$sCacheFileName = ''; $sCacheFileName = '';
if ($bCacheEnabled) if ($bCacheEnabled) {
{
$sCacheFileName = KeyPathHelper::LangCache( $sCacheFileName = KeyPathHelper::LangCache(
$sLanguage, $bAdmin, $this->oActions->Plugins()->Hash()); $sLanguage, $bAdmin, $this->oActions->Plugins()->Hash());
$sResult = $this->Cacher()->Get($sCacheFileName); $sResult = $this->Cacher()->Get($sCacheFileName);
} }
if (!\strlen($sResult)) if (!\strlen($sResult)) {
{
$sResult = $this->oActions->compileLanguage($sLanguage, $bAdmin); $sResult = $this->oActions->compileLanguage($sLanguage, $bAdmin);
if ($bCacheEnabled && \strlen($sCacheFileName)) if ($bCacheEnabled && \strlen($sCacheFileName)) {
{
$this->Cacher()->Set($sCacheFileName, $sResult); $this->Cacher()->Set($sCacheFileName, $sResult);
} }
} }
if ($bCacheEnabled) if ($bCacheEnabled) {
{
$this->oActions->cacheByKey($this->sQuery); $this->oActions->cacheByKey($this->sQuery);
} }
} }
@ -653,13 +605,11 @@ class ServiceActions
$oAccount = null; $oAccount = null;
$sSsoHash = $_REQUEST['hash'] ?? ''; $sSsoHash = $_REQUEST['hash'] ?? '';
if (!empty($sSsoHash)) if (!empty($sSsoHash)) {
{
$mData = null; $mData = null;
$sSsoSubData = $this->Cacher()->Get(KeyPathHelper::SsoCacherKey($sSsoHash)); $sSsoSubData = $this->Cacher()->Get(KeyPathHelper::SsoCacherKey($sSsoHash));
if (!empty($sSsoSubData)) if (!empty($sSsoSubData)) {
{
$aData = \SnappyMail\Crypt::DecryptFromJSON($sSsoSubData, $sSsoHash); $aData = \SnappyMail\Crypt::DecryptFromJSON($sSsoSubData, $sSsoHash);
$this->Cacher()->Delete(KeyPathHelper::SsoCacherKey($sSsoHash)); $this->Cacher()->Delete(KeyPathHelper::SsoCacherKey($sSsoHash));
@ -677,29 +627,24 @@ class ServiceActions
{ {
$oAccount = $this->oActions->LoginProcess($sEmail, $sPassword); $oAccount = $this->oActions->LoginProcess($sEmail, $sPassword);
if ($aAdditionalOptions) if ($aAdditionalOptions) {
{
$bNeedToSettings = false; $bNeedToSettings = false;
$oSettings = $this->SettingsProvider()->Load($oAccount); $oSettings = $this->SettingsProvider()->Load($oAccount);
if ($oSettings) if ($oSettings) {
{
$sLanguage = isset($aAdditionalOptions['Language']) ? $sLanguage = isset($aAdditionalOptions['Language']) ?
$aAdditionalOptions['Language'] : ''; $aAdditionalOptions['Language'] : '';
if ($sLanguage) if ($sLanguage) {
{
$sLanguage = $this->oActions->ValidateLanguage($sLanguage); $sLanguage = $this->oActions->ValidateLanguage($sLanguage);
if ($sLanguage !== $oSettings->GetConf('Language', '')) if ($sLanguage !== $oSettings->GetConf('Language', '')) {
{
$bNeedToSettings = true; $bNeedToSettings = true;
$oSettings->SetConf('Language', $sLanguage); $oSettings->SetConf('Language', $sLanguage);
} }
} }
} }
if ($bNeedToSettings) if ($bNeedToSettings) {
{
$this->SettingsProvider()->Save($oAccount, $oSettings); $this->SettingsProvider()->Save($oAccount, $oSettings);
} }
} }