Capability improvements

Additional branding options
This commit is contained in:
RainLoop Team 2015-05-20 02:05:54 +04:00
parent 7fce424758
commit 763fae345b
46 changed files with 880 additions and 556 deletions

View file

@ -907,7 +907,7 @@ END;
public static function GetClearDomainName($sDomain)
{
$sResultDomain = \preg_replace(
'/^(webmail|email|mail|www|imap4|pop3|imap|pop|demo|client|ssl|secure)\./i',
'/^(webmail|email|mail|www|imap4|pop3|imap|pop|demo|client|ssl|secure|test|cloud|box|m)\./i',
'', $sDomain);
return false === \strpos($sResultDomain, '.') ? $sDomain : $sResultDomain;

View file

@ -46,6 +46,11 @@ class Config
*/
public static $MessageListDateFilter = 0;
/**
* @var string
*/
public static $MessageListPermanentFilter = '';
/**
* @var int
*/

View file

@ -22,5 +22,6 @@ class FolderResponseStatus
const RECENT = 'RECENT';
const UNSEEN = 'UNSEEN';
const UIDNEXT = 'UIDNEXT';
const HIGHESTMODSEQ = 'HIGHESTMODSEQ';
const UIDVALIDITY = 'UIDVALIDITY';
}

View file

@ -22,5 +22,6 @@ class FolderStatus
const RECENT = 'RECENT';
const UNSEEN = 'UNSEEN';
const UIDNEXT = 'UIDNEXT';
const HIGHESTMODSEQ = 'HIGHESTMODSEQ';
const UIDVALIDITY = 'UIDVALIDITY';
}

View file

@ -62,6 +62,11 @@ class FolderInformation
*/
public $Uidnext;
/**
* @var string
*/
public $HighestModSeq;
/**
* @access private
*
@ -79,6 +84,7 @@ class FolderInformation
$this->Unread = null;
$this->Uidnext = null;
$this->HighestModSeq = null;
}
/**

View file

@ -326,7 +326,24 @@ class ImapClient extends \MailSo\Net\NetClient
try
{
$this->SendRequestWithCheck('AUTHENTICATE', array('XOAUTH2', \trim($sXOAuth2Token)));
$this->SendRequest('AUTHENTICATE', array('XOAUTH2', \trim($sXOAuth2Token)));
$aR = $this->parseResponseWithValidation();
if (\is_array($aR) && 0 < \count($aR) && isset($aR[\count($aR) - 1]))
{
$oR = $aR[\count($aR) - 1];
if (\MailSo\Imap\Enumerations\ResponseType::CONTINUATION === $oR->ResponseType)
{
if (!empty($oR->ResponseList[1]) && preg_match('/^[a-zA-Z0-9=+\/]+$/', $oR->ResponseList[1]))
{
$this->Logger()->Write(\base64_decode($oR->ResponseList[1]),
\MailSo\Log\Enumerations\Type::WARNING);
}
$this->sendRaw('');
$this->parseResponseWithValidation();
}
}
}
catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException)
{
@ -681,6 +698,7 @@ class ImapClient extends \MailSo\Net\NetClient
{
$sName = null;
$aStatus = array();
foreach ($oImapResponse->ResponseList[3] as $sArrayItem)
{
if (null === $sName)
@ -734,17 +752,21 @@ class ImapClient extends \MailSo\Net\NetClient
$this->EscapeString($sListPattern)
);
if ($bUseListStatus && $this->IsSupported('LIST-STATUS'))
if ($bUseListStatus && !$bIsSubscribeList && $this->IsSupported('LIST-STATUS'))
{
$aParameters[] = 'RETURN';
$aParameters[] = array(
'STATUS',
array(
\MailSo\Imap\Enumerations\FolderStatus::MESSAGES,
\MailSo\Imap\Enumerations\FolderStatus::UNSEEN,
\MailSo\Imap\Enumerations\FolderStatus::UIDNEXT
)
$aL = array(
\MailSo\Imap\Enumerations\FolderStatus::MESSAGES,
\MailSo\Imap\Enumerations\FolderStatus::UNSEEN,
\MailSo\Imap\Enumerations\FolderStatus::UIDNEXT
);
// if ($this->IsSupported('CONDSTORE'))
// {
// $aL[] = \MailSo\Imap\Enumerations\FolderStatus::HIGHESTMODSEQ;
// }
$aParameters[] = 'RETURN';
$aParameters[] = array('STATUS', $aL);
}
else
{
@ -846,6 +868,12 @@ class ImapClient extends \MailSo\Net\NetClient
{
$oResult->Uidnext = $oImapResponse->OptionalResponse[1];
}
else if ('HIGHESTMODSEQ' === $oImapResponse->OptionalResponse[0] &&
isset($oImapResponse->OptionalResponse[1]) &&
\is_numeric($oImapResponse->OptionalResponse[1]))
{
$oResult->HighestModSeq = \trim($oImapResponse->OptionalResponse[1]);
}
}
if (\count($oImapResponse->ResponseList) > 2 &&

View file

@ -684,16 +684,25 @@ class MailClient
* @param int $iCount
* @param int $iUnseenCount
* @param string $sUidNext
* @param string $sHighestModSeq
*
* @return void
*/
protected function initFolderValues($sFolderName, &$iCount, &$iUnseenCount, &$sUidNext)
protected function initFolderValues($sFolderName, &$iCount, &$iUnseenCount,
&$sUidNext, &$sHighestModSeq = '')
{
$aFolderStatus = $this->oImapClient->FolderStatus($sFolderName, array(
$aTypes = array(
\MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES,
\MailSo\Imap\Enumerations\FolderResponseStatus::UNSEEN,
\MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT
));
);
if ($this->oImapClient->IsSupported('CONDSTORE'))
{
$aTypes[] = \MailSo\Imap\Enumerations\FolderResponseStatus::HIGHESTMODSEQ;
}
$aFolderStatus = $this->oImapClient->FolderStatus($sFolderName, $aTypes);
$iCount = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES])
? (int) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::MESSAGES] : 0;
@ -704,6 +713,9 @@ class MailClient
$sUidNext = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT])
? (string) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::UIDNEXT] : '0';
$sHighestModSeq = isset($aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::HIGHESTMODSEQ])
? (string) $aFolderStatus[\MailSo\Imap\Enumerations\FolderResponseStatus::HIGHESTMODSEQ] : '';
if ($this->IsGmail())
{
$oFolder = $this->oImapClient->FolderCurrentInformation();
@ -735,14 +747,15 @@ class MailClient
* @param int $iCount
* @param int $iUnseenCount
* @param string $sUidNext
* @param string $sHighestModSeq = ''
*
* @return string
*/
public function GenerateFolderHash($sFolder, $iCount, $iUnseenCount, $sUidNext)
public function GenerateFolderHash($sFolder, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq = '')
{
$iUnseenCount = 0; // unneccessery
return \md5('FolderHash/'.$sFolder.'-'.$iCount.'-'.$iUnseenCount.'-'.$sUidNext.'-'.
$this->GenerateImapClientHash()
$sHighestModSeq.'-'.$this->GenerateImapClientHash()
);
}
@ -866,16 +879,18 @@ class MailClient
$iCount = 0;
$iUnseenCount = 0;
$sUidNext = '0';
$sHighestModSeq = '';
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext);
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq);
$aResult = array(
'Folder' => $sFolderName,
'Hash' => $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext),
'Hash' => $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq),
'MessageCount' => $iCount,
'MessageUnseenCount' => $iUnseenCount,
'UidNext' => $sUidNext,
'Flags' => $aFlags,
'HighestModSeq' => $sHighestModSeq,
'NewMessages' => 'INBOX' === $sFolderName ?
$this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext) : array()
);
@ -897,10 +912,11 @@ class MailClient
$iCount = 0;
$iUnseenCount = 0;
$sUidNext = '0';
$sHighestModSeq = '';
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext);
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq);
return $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext);
return $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext, $sHighestModSeq);
}
/**
@ -1124,12 +1140,13 @@ class MailClient
/**
* @param string $sSearch
* @param string $sFilter
* @param int $iTimeZoneOffset = 0
* @param bool $bUseCache = true
*
* @return string
*/
private function getImapSearchCriterias($sSearch, $iTimeZoneOffset = 0, &$bUseCache = true)
private function getImapSearchCriterias($sSearch, $sFilter, $iTimeZoneOffset = 0, &$bUseCache = true)
{
$bUseCache = true;
$iTimeFilter = 0;
@ -1370,14 +1387,25 @@ class MailClient
$sCriteriasResult .= ' SINCE '.\gmdate('j-M-Y', $iTimeFilter);
}
$sCriteriasResult = \trim($sCriteriasResult);
$sCriteriasResult .= ' NOT DELETED';
$sFilter = \trim($sFilter);
if ('' !== $sFilter)
{
$sCriteriasResult .= ' '.$sFilter;
}
$sCriteriasResult = \trim($sCriteriasResult);
if ('' !== \MailSo\Config::$MessageListPermanentFilter)
{
$sCriteriasResult .= ' '.\MailSo\Config::$MessageListPermanentFilter;
}
$sCriteriasResult = \trim($sCriteriasResult);
if ('' === $sCriteriasResult)
{
$sCriteriasResult = 'NOT DELETED'; // ALL
}
else
{
$sCriteriasResult .= ' NOT DELETED';
$sCriteriasResult = 'ALL';
}
return $sCriteriasResult;
@ -1704,190 +1732,6 @@ class MailClient
$this->oImapClient->IsSupported('THREAD=ORDEREDSUBJECT');
}
/**
* @param string $sSearch
* @param string $sFolderName
* @param string|bool $sFolderHash
* @param bool $bUseSortIfSupported = true
* @param bool $bUseESearchOrESortRequest = false
* @param \MailSo\Cache\CacheClient|null $oCacher = null
*
* @return Array|bool
*/
private function getSearchUidsResult($sSearch, $sFolderName, $sFolderHash,
$bUseSortIfSupported = true, $bUseESearchOrESortRequest = false, $oCacher = null)
{
$aResultUids = false;
$bUidsFromCacher = false;
$bUseCacheAfterSearch = true;
$sSerializedHash = '';
$bESortSupported = $bUseSortIfSupported && $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESORT') : false;
$bESearchSupported = $bUseESearchOrESortRequest ? $this->oImapClient->IsSupported('ESEARCH') : false;
$bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false;
$sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, $bUseCacheAfterSearch);
if ($bUseCacheAfterSearch && $oCacher && $oCacher->IsInited())
{
$sSerializedHash = 'SearchSortUids/'.
($bUseSortIfSupported ? 'S': 'N').'/'.
$this->GenerateImapClientHash().'/'.
$sFolderName.'/'.$sSearchCriterias;
$sSerializedLog = '"'.$sFolderName.'" / '.$sSearchCriterias.'';
$sSerialized = $oCacher->Get($sSerializedHash);
if (!empty($sSerialized))
{
$aSerialized = @\json_decode($sSerialized, true);
if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) &&
$sFolderHash === $aSerialized['FolderHash'] &&
\is_array($aSerialized['Uids'])
)
{
if ($this->oLogger)
{
$this->oLogger->Write('Get Serialized UIDS from cache ('.$sSerializedLog.') [count:'.\count($aSerialized['Uids']).']');
}
$aResultUids = $aSerialized['Uids'];
$bUidsFromCacher = true;
}
}
}
if (!\is_array($aResultUids))
{
if ($bUseSortIfSupported)
{
if ($bESortSupported)
{
$aESorthData = $this->oImapClient->MessageSimpleESort(array('ARRIVAL'), $sSearchCriterias, array('ALL'), true, '');
if (isset($aESorthData['ALL']))
{
$aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESorthData['ALL']);
$aResultUids = \array_reverse($aResultUids);
}
unset($aESorthData);
}
else
{
$aResultUids = $this->oImapClient->MessageSimpleSort(array('REVERSE ARRIVAL'), $sSearchCriterias, true);
}
}
else
{
if (!\MailSo\Base\Utils::IsAscii($sSearch))
{
try
{
if ($bESearchSupported)
{
$aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), true, '', 'UTF-8');
if (isset($aESearchData['ALL']))
{
$aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']);
$aResultUids = \array_reverse($aResultUids);
}
unset($aESearchData);
}
else
{
$aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true, 'UTF-8');
}
}
catch (\MailSo\Imap\Exceptions\NegativeResponseException $oException)
{
$oException = null;
$aResultUids = false;
}
}
if (false === $aResultUids)
{
if ($bESearchSupported)
{
$aESearchData = $this->oImapClient->MessageSimpleESearch($sSearchCriterias, array('ALL'), true);
if (isset($aESearchData['ALL']))
{
$aResultUids = \MailSo\Base\Utils::ParseFetchSequence($aESearchData['ALL']);
$aResultUids = \array_reverse($aResultUids);
}
unset($aESearchData);
}
else
{
$aResultUids = $this->oImapClient->MessageSimpleSearch($sSearchCriterias, true);
}
}
}
if (!$bUidsFromCacher && $bUseCacheAfterSearch && \is_array($aResultUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash))
{
$oCacher->Set($sSerializedHash, @\json_encode(array(
'FolderHash' => $sFolderHash,
'Uids' => $aResultUids
)));
if ($this->oLogger)
{
$this->oLogger->Write('Save Serialized UIDS to cache ('.$sSerializedLog.') [count:'.\count($aResultUids).']');
}
}
}
return $aResultUids;
}
/**
* @param string $sFolderName
* @param string $sFolderHash
* @param string $sUid
* @param \MailSo\Cache\CacheClient|null $oCacher = null
*
* @return array
*/
public function MessageThreadUidsFromCache($sFolderName, $sFolderHash, $sUid, $oCacher = null)
{
$aResult = array();
if (0 < \strlen($sFolderName) && 0 < \strlen($sFolderHash) && 0 < \strlen($sUid) && $oCacher && $oCacher->IsInited())
{
$mThreads = $this->MessageListThreadsMap($sFolderName, $sFolderHash, array(), $oCacher, true);
if (\is_array($mThreads))
{
$iUid = (int) $sUid;
foreach ($mThreads as $iSubUid => $aSubUids)
{
if ($iUid === $iSubUid)
{
$aResult = $aSubUids;
if (!\is_array($aResult))
{
$aResult = array();
}
\array_unshift($aResult, $iSubUid);
break;
}
else if (\is_array($aSubUids))
{
if (\in_array($iUid, $aSubUids))
{
$aResult = $aSubUids;
\array_unshift($aResult, $iSubUid);
break;
}
}
}
}
}
return \array_map('trim', $aResult);
}
/**
* @param string $sFolderName
* @param array $aUids
@ -1918,6 +1762,7 @@ class MailClient
/**
* @param \MailSo\Cache\CacheClient|null $oCacher
* @param string $sSearch
* @param string $sFilter
* @param string $sFolderName
* @param string $sFolderHash
* @param bool $bUseSortIfSupported = false
@ -1928,7 +1773,7 @@ class MailClient
* @throws \MailSo\Net\Exceptions\Exception
* @throws \MailSo\Imap\Exceptions\Exception
*/
public function GetUids($oCacher, $sSearch, $sFolderName, $sFolderHash, $bUseSortIfSupported = false)
public function GetUids($oCacher, $sSearch, $sFilter, $sFolderName, $sFolderHash, $bUseSortIfSupported = false)
{
$aResultUids = false;
$bUidsFromCacher = false;
@ -1944,7 +1789,7 @@ class MailClient
$bUseSortIfSupported = false;
}
$sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, $bUseCacheAfterSearch);
$sSearchCriterias = $this->getImapSearchCriterias($sSearch, $sFilter, 0, $bUseCacheAfterSearch);
if ($bUseCacheAfterSearch && $oCacher && $oCacher->IsInited())
{
$sSerializedHash = 'GetUids/'.
@ -2009,6 +1854,7 @@ class MailClient
* @param bool $bUseThreadSortIfSupported = false
* @param bool $bUseESearchOrESortRequest = false
* @param string $sThreadUid = ''
* @param string $sFilter = ''
*
* @return \MailSo\Mail\MessageCollection
*
@ -2017,8 +1863,9 @@ class MailClient
* @throws \MailSo\Imap\Exceptions\Exception
*/
public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null,
$bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $sThreadUid = '')
$bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $sThreadUid = '', $sFilter = '')
{
$sFilter = \trim($sFilter);
$sSearch = \trim($sSearch);
if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) ||
!\MailSo\Base\Validator::RangeInt($iLimit, 0, 999))
@ -2026,6 +1873,8 @@ class MailClient
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
}
$bUseFilter = '' !== $sFilter;
$this->oImapClient->FolderSelect($sFolderName);
$oMessageCollection = MessageCollection::NewInstance();
@ -2044,6 +1893,7 @@ class MailClient
$iMessageRealCount = 0;
$iMessageUnseenCount = 0;
$sUidNext = '0';
$sHighestModSeq = '';
$bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false;
@ -2060,9 +1910,16 @@ class MailClient
$oCacher = null;
}
$this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
$this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq);
if ($bUseFilter)
{
$iMessageUnseenCount = 0;
}
$oMessageCollection->FolderHash = $this->GenerateFolderHash(
$sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext, $sHighestModSeq);
$oMessageCollection->FolderHash = $this->GenerateFolderHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
$oMessageCollection->UidNext = $sUidNext;
if (empty($sThreadUid) && 0 < \strlen($sPrevUidNext) && 'INBOX' === $sFolderName)
@ -2083,7 +1940,7 @@ class MailClient
if (0 < $iMessageRealCount)
{
$mAllSortedUids = $this->GetUids($oCacher, '',
$mAllSortedUids = $this->GetUids($oCacher, '', $sFilter,
$oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported);
$mAllThreads = $bUseThreadSortIfSupported ? $this->MessageListThreadsMap(
@ -2132,7 +1989,7 @@ class MailClient
if (0 < \strlen($sSearch) && \is_array($aUids))
{
$aSearchedUids = $this->GetUids($oCacher, $sSearch, $oMessageCollection->FolderName, $oMessageCollection->FolderHash);
$aSearchedUids = $this->GetUids($oCacher, $sSearch, $sFilter, $oMessageCollection->FolderName, $oMessageCollection->FolderHash);
if (\is_array($aSearchedUids) && 0 < \count($aSearchedUids))
{
$aFlippedSearchedUids = \array_flip($aSearchedUids);
@ -2678,7 +2535,7 @@ class MailClient
$this->oImapClient->FolderSelect($sFolderFullNameRaw);
$oFolderInformation = $this->oImapClient->FolderCurrentInformation();
if ($oFolderInformation && 0 < $oFolderInformation->Exists) // STATUS?
if ($oFolderInformation && $oFolderInformation->Exists && 0 < $oFolderInformation->Exists) // STATUS?
{
$this->oImapClient->MessageStoreFlag('1:*', false,
array(\MailSo\Imap\Enumerations\MessageFlag::DELETED),

View file

@ -893,9 +893,16 @@ class Actions
{
if (null === $this->oAddressBookProvider)
{
$this->oAddressBookProvider = new \RainLoop\Providers\AddressBook(
$this->Config()->Get('contacts', 'enable', false) || $bForceEnable ? $this->fabrica('address-book', $oAccount) : null);
$oDriver = null;
if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::CONTACTS, $oAccount))
{
if ($this->Config()->Get('contacts', 'enable', false) || $bForceEnable)
{
$oDriver = $this->fabrica('address-book', $oAccount);
}
}
$this->oAddressBookProvider = new \RainLoop\Providers\AddressBook($oDriver);
$this->oAddressBookProvider->SetLogger($this->Logger());
}
@ -1078,7 +1085,7 @@ class Actions
$this->oLoggerAuth->AddForbiddenType(\MailSo\Log\Enumerations\Type::TIME_DELTA);
$oDriver = \MailSo\Log\Drivers\File::NewInstance($sAuthLogFileFullPath);
$oDriver->DisableTimePrefix();
$oDriver->DisableGuidPrefix();
$oDriver->DisableTypedPrefix();
@ -1344,6 +1351,7 @@ class Actions
'LoginCss' => '',
'UserLogo' => '',
'UserLogoTitle' => '',
'UserLogoMessage' => '',
'UserCss' => '',
'WelcomePageUrl' => '',
'WelcomePageDisplay' => 'none',
@ -1357,7 +1365,6 @@ class Actions
'AllowCtrlEnterOnCompose' => (bool) $oConfig->Get('labs', 'allow_ctrl_enter_on_compose', false),
'UseRsaEncryption' => (bool) $oConfig->Get('security', 'use_rsa_encryption', false),
'RsaPublicKey' => '',
'HideDangerousActions' => $oConfig->Get('labs', 'hide_dangerous_actions', false),
'CustomLoginLink' => $oConfig->Get('labs', 'custom_login_link', ''),
'CustomLogoutLink' => $oConfig->Get('labs', 'custom_logout_link', ''),
'LoginDefaultDomain' => $oConfig->Get('login', 'default_domain', ''),
@ -1383,7 +1390,7 @@ class Actions
'Plugins' => array()
);
if ($oConfig->Get('capa', 'attachments_actions', false))
if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::ATTACHMENTS_ACTIONS))
{
if (!!\class_exists('ZipArchive'))
{
@ -1404,7 +1411,6 @@ class Actions
$aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false);
$aResult['DropboxApiKey'] = \trim($oConfig->Get('social', 'dropbox_api_key', ''));
if ($aResult['UseRsaEncryption'] &&
\file_exists(APP_PRIVATE_DATA.'rsa/public') && \file_exists(APP_PRIVATE_DATA.'rsa/private'))
{
@ -1417,7 +1423,7 @@ class Actions
}
}
if (0 === strlen($aResult['RsaPublicKey']))
if (0 === \strlen($aResult['RsaPublicKey']))
{
$aResult['UseRsaEncryption'] = false;
}
@ -2749,7 +2755,7 @@ class Actions
*/
public function DoAttachmentsActions()
{
if (!$this->Config()->Get('capa', 'attachments_actions', false))
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::ATTACHMENTS_ACTIONS))
{
return $this->FalseResponse(__FUNCTION__);
}
@ -3491,7 +3497,7 @@ class Actions
$this->setConfigFromParams($oConfig, $sParamName, 'webmail', 'allow_additional_identities', 'bool');
break;
case \RainLoop\Enumerations\Capa::TEMPLATES:
$this->setConfigFromParams($oConfig, $sParamName, 'capa', 'templates', 'bool');
$this->setConfigFromParams($oConfig, $sParamName, 'capa', 'x-templates', 'bool');
break;
case \RainLoop\Enumerations\Capa::TWO_FACTOR:
$this->setConfigFromParams($oConfig, $sParamName, 'security', 'allow_two_factor_auth', 'bool');
@ -5126,9 +5132,6 @@ class Actions
*/
public function DoFolders()
{
// \sleep(1);
// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError);
$oAccount = $this->initMailClientConnection();
$oFolderCollection = null;
@ -5136,7 +5139,8 @@ class Actions
if (null === $oFolderCollection)
{
$oFolderCollection = $this->MailClient()->Folders('', '*',
$oFolderCollection = $this->MailClient()->Folders('',
$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount) ? '*' : 'INBOX',
!!$this->Config()->Get('labs', 'use_imap_list_subscribe', true),
(int) $this->Config()->Get('labs', 'imap_folder_list_limit', 200)
);
@ -5152,7 +5156,8 @@ class Actions
$this->recFoldersTypes($oAccount, $oFolderCollection, $aSystemFolders);
$oFolderCollection->SystemFolders = $aSystemFolders;
if ($this->Config()->Get('labs', 'autocreate_system_folders', true))
if ($this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount) &&
$this->Config()->Get('labs', 'autocreate_system_folders', true))
{
$bDoItAgain = false;
@ -5272,10 +5277,12 @@ class Actions
*/
public function DoFolderCreate()
{
// \sleep(1);
// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantCreateFolder);
$oAccount = $this->initMailClientConnection();
$this->initMailClientConnection();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
try
{
@ -5298,7 +5305,12 @@ class Actions
*/
public function DoFolderSubscribe()
{
$this->initMailClientConnection();
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
$sFolderFullNameRaw = $this->GetActionParam('Folder', '');
$bSubscribe = '1' === (string) $this->GetActionParam('Subscribe', '0');
@ -5329,6 +5341,11 @@ class Actions
{
$oAccount = $this->getAccountFromToken();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
$sFolderFullNameRaw = $this->GetActionParam('Folder', '');
$bCheckable = '1' === (string) $this->GetActionParam('Checkable', '0');
@ -5374,7 +5391,12 @@ class Actions
*/
public function DoFolderRename()
{
$this->initMailClientConnection();
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
$sPrevFolderFullNameRaw = $this->GetActionParam('Folder', '');
$sNewTopFolderNameInUtf = $this->GetActionParam('NewFolderName', '');
@ -5399,10 +5421,12 @@ class Actions
*/
public function DoFolderDelete()
{
// \sleep(1);
// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantRenameFolder);
$oAccount = $this->initMailClientConnection();
$this->initMailClientConnection();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::FOLDERS, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
$sFolderFullNameRaw = $this->GetActionParam('Folder', '');
@ -5619,7 +5643,8 @@ class Actions
$this->cacherForUids(),
!!$this->Config()->Get('labs', 'use_imap_sort', false),
$bUseThreads,
$sThreadUid
$sThreadUid,
''
);
}
catch (\Exception $oException)
@ -5886,6 +5911,11 @@ class Actions
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
$sMessageFolder = $this->GetActionParam('MessageFolder', '');
$sMessageUid = $this->GetActionParam('MessageUid', '');
@ -6098,6 +6128,11 @@ class Actions
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
$oConfig = $this->Config();
$sDraftFolder = $this->GetActionParam('MessageFolder', '');
@ -6283,6 +6318,11 @@ class Actions
{
$oAccount = $this->initMailClientConnection();
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount))
{
return $this->FalseResponse(__FUNCTION__);
}
$oMessage = $this->buildReadReceiptMessage($oAccount);
$this->Plugins()->RunHook('filter.send-read-receipt-message', array(&$oMessage, $oAccount));
@ -7875,10 +7915,10 @@ class Actions
}
}
// if ($oConfig->Get('capa', 'templates', true))
// {
// $aResult[] = \RainLoop\Enumerations\Capa::TEMPLATES;
// }
if ($oConfig->Get('capa', 'x-templates', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::TEMPLATES;
}
if ($oConfig->Get('webmail', 'allow_additional_accounts', false))
{
@ -7890,6 +7930,66 @@ class Actions
$aResult[] = \RainLoop\Enumerations\Capa::IDENTITIES;
}
if ($oConfig->Get('capa', 'folders', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::FOLDERS;
if ($oConfig->Get('capa', 'messagelist_actions', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::MESSAGELIST_ACTIONS;
if ($oConfig->Get('capa', 'dangerous_actions', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::DANGEROUS_ACTIONS;
}
}
}
if ($oConfig->Get('capa', 'reload', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::RELOAD;
}
if ($oConfig->Get('capa', 'settings', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::SETTINGS;
}
if ($oConfig->Get('capa', 'help', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::HELP;
}
if ($oConfig->Get('capa', 'attachments_actions', false))
{
$aResult[] = \RainLoop\Enumerations\Capa::ATTACHMENTS_ACTIONS;
}
if ($oConfig->Get('capa', 'message_actions', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::MESSAGE_ACTIONS;
}
if ($oConfig->Get('capa', 'composer', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::COMPOSER;
if ($oConfig->Get('capa', 'contacts', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::CONTACTS;
}
}
if ($oConfig->Get('capa', 'search', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::SEARCH;
if ($oConfig->Get('capa', 'search_adv', true))
{
$aResult[] = \RainLoop\Enumerations\Capa::SEARCH_ADV;
}
}
if ($oConfig->Get('security', 'allow_two_factor_auth', false) &&
($bAdmin || ($oAccount && !$oAccount->IsAdditionalAccount())))
{
@ -9219,7 +9319,7 @@ class Actions
}
else if ('MailSo\Mail\Message' === $sClassName)
{
$oAccount = call_user_func($fGetAccount);
$oAccount = \call_user_func($fGetAccount);
$mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
'Folder' => $mResponse->Folder(),
@ -9275,6 +9375,11 @@ class Actions
$mResult['IsForwarded'] = 0 < \strlen($sForwardedFlag) && \in_array(\strtolower($sForwardedFlag), $aFlags);
$mResult['IsReadReceipt'] = 0 < \strlen($sReadReceiptFlag) && \in_array(\strtolower($sReadReceiptFlag), $aFlags);
if (!$this->GetCapa(false, \RainLoop\Enumerations\Capa::COMPOSER, $oAccount))
{
$mResult['IsReadReceipt'] = true;
}
$mResult['TextPartIsTrimmed'] = false;
if ('Message' === $sParent)
@ -9483,17 +9588,19 @@ class Actions
else if ('MailSo\Mail\Folder' === $sClassName)
{
$aExtended = null;
$mStatus = $mResponse->Status();
if (\is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT']))
{
$aExtended = array(
'MessageCount' => (int) $mStatus['MESSAGES'],
'MessageUnseenCount' => (int) $mStatus['UNSEEN'],
'UidNext' => (string) $mStatus['UIDNEXT'],
'Hash' => $this->MailClient()->GenerateFolderHash(
$mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'])
);
}
// $mStatus = $mResponse->Status();
// if (\is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT']))
// {
// $aExtended = array(
// 'MessageCount' => (int) $mStatus['MESSAGES'],
// 'MessageUnseenCount' => (int) $mStatus['UNSEEN'],
// 'UidNext' => (string) $mStatus['UIDNEXT'],
// 'Hash' => $this->MailClient()->GenerateFolderHash(
// $mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'],
// empty($mStatus['HIGHESTMODSEQ']) ? '' : $mStatus['HIGHESTMODSEQ'])
// );
// }
$aCheckableFolder = \call_user_func($fGetCheckableFolder);
if (!\is_array($aCheckableFolder))

View file

@ -91,9 +91,13 @@ class Api
\MailSo\Config::$MessageListDateFilter =
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_date_filter', 0);
\MailSo\Config::$MessageListPermanentFilter =
\trim(\RainLoop\Api::Config()->Get('labs', 'imap_message_list_permanent_filter', ''));
\MailSo\Config::$LargeThreadLimit =
(int) \RainLoop\Api::Config()->Get('labs', 'imap_large_thread_limit', 50);
\MailSo\Config::$SystemLogger = \RainLoop\Api::Logger();
$sSslCafile = \RainLoop\Api::Config()->Get('ssl', 'cafile', '');

View file

@ -91,6 +91,7 @@ class Application extends \RainLoop\Config\AbstractConfig
'login_powered' => array(true),
'user_logo' => array(''),
'user_logo_title' => array(''),
'user_logo_message' => array(''),
'user_css' => array(''),
'welcome_page_url' => array(''),
'welcome_page_display' => array('none')
@ -134,8 +135,19 @@ class Application extends \RainLoop\Config\AbstractConfig
),
'capa' => array(
'folders' => array(true),
'composer' => array(true),
'contacts' => array(true),
'settings' => array(true),
'help' => array(true),
'reload' => array(true),
'search' => array(true),
'search_adv' => array(true),
'filters' => array(true),
'templates' => array(true),
'x-templates' => array(false),
'dangerous_actions' => array(true),
'message_actions' => array(true),
'messagelist_actions' => array(true),
'attachments_actions' => array(true)
),
@ -299,6 +311,7 @@ Enables caching in the system'),
'imap_message_list_fast_simple_search' => array(true),
'imap_message_list_count_limit_trigger' => array(0),
'imap_message_list_date_filter' => array(0),
'imap_message_list_permanent_filter' => array(''),
'imap_large_thread_limit' => array(50),
'imap_folder_list_limit' => array(200),
'imap_show_login_alert' => array(true),

View file

@ -17,6 +17,18 @@ class Capa
const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS';
const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS';
const IDENTITIES = 'IDENTITIES';
const FOLDERS = 'FOLDERS';
const COMPOSER = 'COMPOSER';
const CONTACTS = 'CONTACTS';
const RELOAD = 'RELOAD';
const SEARCH = 'SEARCH';
const SEARCH_ADV = 'SEARCH_ADV';
const SETTINGS = 'SETTINGS';
const HELP = 'HELP';
const TEMPLATES = 'TEMPLATES';
const MESSAGE_ACTIONS = 'MESSAGE_ACTIONS';
const MESSAGELIST_ACTIONS = 'MESSAGELIST_ACTIONS';
const ATTACHMENTS_ACTIONS = 'ATTACHMENTS_ACTIONS';
const DANGEROUS_ACTIONS = 'DANGEROUS_ACTIONS';
const AUTOLOGOUT = 'AUTOLOGOUT';
}

View file

@ -437,8 +437,18 @@ class Account extends \RainLoop\Account // for backward compatibility
}
else
{
$oMailClient->Login($aImapCredentials['Login'], $aImapCredentials['Password'], '',
$aImapCredentials['UseAuthPlainIfSupported']);
$iGatLen = \strlen(APP_GOOGLE_ACCESS_TOKEN_PREFIX);
$sPassword = $aImapCredentials['Password'];
if (APP_GOOGLE_ACCESS_TOKEN_PREFIX === \substr($sPassword, 0, $iGatLen))
{
$oMailClient->LoginWithXOauth2(
\base64_encode('user='.$aImapCredentials['Login']."\1".'auth=Bearer '.\substr($sPassword, $iGatLen)."\1\1"));
}
else
{
$oMailClient->Login($aImapCredentials['Login'], $aImapCredentials['Password'], '',
$aImapCredentials['UseAuthPlainIfSupported']);
}
}
$bLogin = true;
@ -495,7 +505,17 @@ class Account extends \RainLoop\Account // for backward compatibility
if ($aSmtpCredentials['UseAuth'] && !$aSmtpCredentials['UsePhpMail'] && $oSmtpClient)
{
$oSmtpClient->Login($aSmtpCredentials['Login'], $aSmtpCredentials['Password']);
$iGatLen = \strlen(APP_GOOGLE_ACCESS_TOKEN_PREFIX);
$sPassword = $aSmtpCredentials['Password'];
if (APP_GOOGLE_ACCESS_TOKEN_PREFIX === \substr($sPassword, 0, $iGatLen))
{
$oSmtpClient->LoginWithXOauth2(
\base64_encode('user='.$aSmtpCredentials['Login']."\1".'auth=Bearer '.\substr($sPassword, $iGatLen)."\1\1"));
}
else
{
$oSmtpClient->Login($aSmtpCredentials['Login'], $aSmtpCredentials['Password']);
}
$bLogin = true;
}

View file

@ -766,7 +766,8 @@ class ServiceActions
*/
public function ServiceSocialGoogle()
{
return $this->oActions->Social()->GooglePopupService();
$bXAuth = '1' === (string) $this->oHttp->GetQuery('xauth', '0');
return $this->oActions->Social()->GooglePopupService($bXAuth);
}
/**

View file

@ -125,7 +125,7 @@ class Social
/**
* @return string
*/
public function GooglePopupService()
public function GooglePopupService($bGmail = false)
{
$sResult = '';
$sLoginUrl = '';
@ -152,23 +152,36 @@ class Social
$sState = $this->oHttp->GetQuery('state');
if (!empty($sState))
{
$aParts = explode('|', $sState, 2);
$sCheckToken = !empty($aParts[0]) ? $aParts[0] : '';
$sCheckAuth = !empty($aParts[1]) ? $aParts[1] : '';
$aParts = explode('|', $sState, 3);
if (!$bGmail)
{
$bGmail = !empty($aParts[0]) ? '1' === (string) $aParts[0] : false;
}
$sCheckToken = !empty($aParts[1]) ? $aParts[1] : '';
$sCheckAuth = !empty($aParts[2]) ? $aParts[2] : '';
}
$sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialGoogle';
if (!$this->oHttp->HasQuery('code'))
{
// https://www.google.com/m8/feeds/
$aParams = array(
'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
'state' => \RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(),
// 'access_type' => 'offline',
// 'approval_prompt' => 'force',
'scope' => \trim(\implode(' ', array(
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
$bGmail ? 'https://mail.google.com/' : ''
))),
'state' => ($bGmail ? '1' : '0').'|'.\RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(),
'response_type' => 'code'
);
// if ($bGmail)
// {
// $aParams['access_type'] = 'offline';
// $aParams['approval_prompt'] = 'force';
// }
$sLoginUrl = $oGoogle->getAuthenticationUrl('https://accounts.google.com/o/oauth2/auth', $sRedirectUrl, $aParams);
}
else if (!empty($sState) && $sCheckToken === \RainLoop\Utils::GetConnectionToken())
@ -192,12 +205,26 @@ class Social
{
if ($bLogin)
{
$sUserData = $this->oActions->StorageProvider()->Get(null,
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
$this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id'])
);
$aUserData = null;
if ($bGmail)
{
if (!empty($aUserInfoResponse['result']['email']))
{
$aUserData = array(
'Email' => $aUserInfoResponse['result']['email'],
'Password' => APP_GOOGLE_ACCESS_TOKEN_PREFIX.$aAuthorizationResponse['result']['access_token']
);
}
}
else
{
$sUserData = $this->oActions->StorageProvider()->Get(null,
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
$this->GoogleUserLoginStorageKey($oGoogle, $aUserInfoResponse['result']['id'])
);
$aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
$aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
}
if ($aUserData && \is_array($aUserData) &&
!empty($aUserData['Email']) && isset($aUserData['Password']))
@ -210,7 +237,7 @@ class Social
}
}
if ($oAccount)
if ($oAccount && !$bGmail)
{
$aUserData = array(
'ID' => $aUserInfoResponse['result']['id'],