diff --git a/data/VERSION b/data/VERSION index 2ce0796f24..e58b18e1d3 100644 --- a/data/VERSION +++ b/data/VERSION @@ -1 +1 @@ -1.3.9.485 \ No newline at end of file +1.3.10.490 \ No newline at end of file diff --git a/index.php b/index.php index 651b82dba9..a4f197af47 100644 --- a/index.php +++ b/index.php @@ -1,13 +1,12 @@ array( - 'phpversion' => \phpversion(), + 'phpversion' => PHP_VERSION, 'ssl' => (int) \function_exists('openssl_open'), 'iconv' => (int) \function_exists('iconv') )); diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Base/ResourceRegistry.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Base/ResourceRegistry.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Base/ResourceRegistry.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Base/ResourceRegistry.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/Binary.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/Binary.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/Binary.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/Binary.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/Literal.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/Literal.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/Literal.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/Literal.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/SubStreams.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/Test.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/Test.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Base/StreamWrappers/Test.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Base/StreamWrappers/Test.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Base/Utils.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Base/Utils.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Base/Utils.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Base/Utils.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Base/Validator.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Base/Validator.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Base/Validator.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Base/Validator.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/CacheClient.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/CacheClient.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/CacheClient.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/CacheClient.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/DriverInterface.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/DriverInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/DriverInterface.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/DriverInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/Drivers/APC.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/Drivers/APC.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/Drivers/APC.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/Drivers/APC.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/Drivers/File.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/Drivers/File.php similarity index 90% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/Drivers/File.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/Drivers/File.php index 2c36e80f03..4d15c72fc5 100644 --- a/rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/Drivers/File.php +++ b/rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/Drivers/File.php @@ -1,126 +1,126 @@ -sCacheFolder = $sCacheFolder; - $this->sCacheFolder = rtrim(trim($this->sCacheFolder), '\\/').'/'; - if (!\is_dir($this->sCacheFolder)) - { - @\mkdir($this->sCacheFolder, 0777); - } - } - - /** - * @param string $sCacheFolder - * - * @return \MailSo\Cache\Drivers\File - */ - public static function NewInstance($sCacheFolder) - { - return new self($sCacheFolder); - } - - /** - * @param string $sKey - * @param string $sValue - * - * @return bool - */ - public function Set($sKey, $sValue) - { - return false !== \file_put_contents($sPath = $this->generateCachedFileName($sKey, true), $sValue); - } - - /** - * @param string $sKey - * - * @return string - */ - public function Get($sKey) - { - $sValue = ''; - $sPath = $this->generateCachedFileName($sKey); - if (\file_exists($sPath)) - { - $sValue = \file_get_contents($sPath); - } - - return \is_string($sValue) ? $sValue : ''; - } - - /** - * @param string $sKey - * - * @return void - */ - public function Delete($sKey) - { - $sPath = $this->generateCachedFileName($sKey); - if (\file_exists($sPath)) - { - \unlink($sPath); - } - } - - /** - * @param int $iTimeToClearInHours = 24 - * - * @return bool - */ - public function GC($iTimeToClearInHours = 24) - { - if (0 < $iTimeToClearInHours) - { - \MailSo\Base\Utils::RecTimeDirRemove($this->sCacheFolder, 60 * 60 * $iTimeToClearInHours, \time()); - return true; - } - - return false; - } - - /** - * @param string $sKey - * @param bool $bMkDir = false - * - * @return string - */ - private function generateCachedFileName($sKey, $bMkDir = false) - { - $sFilePath = ''; - if (3 < \strlen($sKey)) - { - $sKeyPath = \sha1($sKey); - $sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath; - - $sFilePath = $this->sCacheFolder.'/'.$sKeyPath; - if ($bMkDir && !\is_dir(\dirname($sFilePath))) - { - if (!\mkdir(\dirname($sFilePath), 0777, true)) - { - $sFilePath = ''; - } - } - } - - return $sFilePath; - } -} +sCacheFolder = $sCacheFolder; + $this->sCacheFolder = rtrim(trim($this->sCacheFolder), '\\/').'/'; + if (!\is_dir($this->sCacheFolder)) + { + @\mkdir($this->sCacheFolder, 0755); + } + } + + /** + * @param string $sCacheFolder + * + * @return \MailSo\Cache\Drivers\File + */ + public static function NewInstance($sCacheFolder) + { + return new self($sCacheFolder); + } + + /** + * @param string $sKey + * @param string $sValue + * + * @return bool + */ + public function Set($sKey, $sValue) + { + return false !== \file_put_contents($sPath = $this->generateCachedFileName($sKey, true), $sValue); + } + + /** + * @param string $sKey + * + * @return string + */ + public function Get($sKey) + { + $sValue = ''; + $sPath = $this->generateCachedFileName($sKey); + if (\file_exists($sPath)) + { + $sValue = \file_get_contents($sPath); + } + + return \is_string($sValue) ? $sValue : ''; + } + + /** + * @param string $sKey + * + * @return void + */ + public function Delete($sKey) + { + $sPath = $this->generateCachedFileName($sKey); + if (\file_exists($sPath)) + { + \unlink($sPath); + } + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + if (0 < $iTimeToClearInHours) + { + \MailSo\Base\Utils::RecTimeDirRemove($this->sCacheFolder, 60 * 60 * $iTimeToClearInHours, \time()); + return true; + } + + return false; + } + + /** + * @param string $sKey + * @param bool $bMkDir = false + * + * @return string + */ + private function generateCachedFileName($sKey, $bMkDir = false) + { + $sFilePath = ''; + if (3 < \strlen($sKey)) + { + $sKeyPath = \sha1($sKey); + $sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath; + + $sFilePath = $this->sCacheFolder.'/'.$sKeyPath; + if ($bMkDir && !\is_dir(\dirname($sFilePath))) + { + if (!\mkdir(\dirname($sFilePath), 0755, true)) + { + $sFilePath = ''; + } + } + } + + return $sFilePath; + } +} diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/Drivers/Memcache.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/Drivers/Memcache.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Cache/Drivers/Memcache.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Cache/Drivers/Memcache.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/BodyStructure.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/BodyStructure.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/BodyStructure.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/BodyStructure.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FetchType.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FetchType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FetchType.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FetchType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FolderResponseStatus.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FolderStatus.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FolderType.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FolderType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/FolderType.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/FolderType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/MessageFlag.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/ResponseStatus.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/ResponseStatus.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/ResponseStatus.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/ResponseStatus.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/ResponseType.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/ResponseType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/ResponseType.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/ResponseType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/StoreAction.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/StoreAction.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Enumerations/StoreAction.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Enumerations/StoreAction.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/InvalidResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/InvalidResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/InvalidResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/InvalidResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/LoginBadCredentialsException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/LoginBadCredentialsException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/LoginBadCredentialsException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/LoginBadCredentialsException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/LoginBadMethodException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/LoginBadMethodException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/LoginBadMethodException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/LoginBadMethodException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/LoginException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/LoginException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/LoginException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/LoginException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/NegativeResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/NegativeResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/NegativeResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/NegativeResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/ResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/ResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/ResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/ResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/ResponseNotFoundException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/RuntimeException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/RuntimeException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Exceptions/RuntimeException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Exceptions/RuntimeException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/FetchResponse.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/FetchResponse.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/FetchResponse.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/FetchResponse.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Folder.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Folder.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Folder.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Folder.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/FolderInformation.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/FolderInformation.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/FolderInformation.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/FolderInformation.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/ImapClient.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/ImapClient.php similarity index 99% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/ImapClient.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/ImapClient.php index 654826b929..9eb8439506 100644 --- a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/ImapClient.php +++ b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/ImapClient.php @@ -1272,6 +1272,7 @@ public function MessageStoreFlag($sIndexRange, $bIndexIsUid, $aInputStoreItems, * @param int $iStreamSize * @param array $aAppendFlags = null * @param int $iUid = null + * @param int $sDateTime = 0 * * @return \MailSo\Imap\ImapClient * @@ -1279,12 +1280,18 @@ public function MessageStoreFlag($sIndexRange, $bIndexIsUid, $aInputStoreItems, * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ - public function MessageAppendStream($sFolderName, $rMessageAppendStream, $iStreamSize, $aAppendFlags = null, &$iUid = null) + public function MessageAppendStream($sFolderName, $rMessageAppendStream, $iStreamSize, $aAppendFlags = null, &$iUid = null, $sDateTime = 0) { - $this->SendRequest('APPEND', - array($this->EscapeString($sFolderName), $aAppendFlags, '{'.$iStreamSize.'}')); + $aData = array($this->EscapeString($sFolderName), $aAppendFlags); + if (0 < $sDateTime) + { + $aData[] = $this->EscapeString(\gmdate('d-M-Y H:i:s', $sDateTime).' +0000'); + } - $this->parseResponseWithValidation('+'); + $aData[] = '{'.$iStreamSize.'}'; + + $this->SendRequest('APPEND', $aData); + $this->parseResponseWithValidation(); $this->writeLog('Write to connection stream', \MailSo\Log\Enumerations\Type::NOTE); diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/NamespaceResult.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/NamespaceResult.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/NamespaceResult.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/NamespaceResult.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Response.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Response.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/Response.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/Response.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/SearchBuilder.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/SearchBuilder.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Imap/SearchBuilder.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Imap/SearchBuilder.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Driver.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Driver.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Driver.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Driver.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Drivers/Callback.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Drivers/Callback.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Drivers/Callback.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Drivers/Callback.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Drivers/File.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Drivers/File.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Drivers/File.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Drivers/File.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Drivers/Inline.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Drivers/Inline.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Drivers/Inline.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Drivers/Inline.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Enumerations/Type.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Enumerations/Type.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Enumerations/Type.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Enumerations/Type.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Logger.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Logger.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Log/Logger.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Log/Logger.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Attachment.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Attachment.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Attachment.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Attachment.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/AttachmentCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/AttachmentCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/AttachmentCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/AttachmentCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Exceptions/NonEmptyFolder.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Exceptions/NonEmptyFolder.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Exceptions/NonEmptyFolder.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Exceptions/NonEmptyFolder.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Exceptions/RuntimeException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Exceptions/RuntimeException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Exceptions/RuntimeException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Exceptions/RuntimeException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Folder.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Folder.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Folder.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Folder.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/FolderCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/FolderCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/FolderCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/FolderCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/MailClient.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/MailClient.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/MailClient.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Message.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Message.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/Message.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/Message.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/MessageCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/MessageCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mail/MessageCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mail/MessageCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/MailSo.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/MailSo.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/MailSo.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/MailSo.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Attachment.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Attachment.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Attachment.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Attachment.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/AttachmentCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/AttachmentCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/AttachmentCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/AttachmentCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Email.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Email.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Email.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Email.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/EmailCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/EmailCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/EmailCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/EmailCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Constants.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Constants.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Constants.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Constants.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Header.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Header.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Header.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Header.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/MessagePriority.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/MessagePriority.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/MessagePriority.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/MessagePriority.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/MimeType.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/MimeType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/MimeType.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/MimeType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Parameter.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Parameter.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Parameter.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Parameter.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Sensitivity.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Sensitivity.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Enumerations/Sensitivity.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Enumerations/Sensitivity.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Header.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Header.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Header.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Header.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/HeaderCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/HeaderCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/HeaderCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/HeaderCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Message.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Message.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Message.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Message.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parameter.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parameter.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parameter.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parameter.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/ParameterCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/ParameterCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/ParameterCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/ParameterCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parser/ParserEmpty.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parser/ParserEmpty.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parser/ParserEmpty.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parser/ParserEmpty.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parser/ParserInterface.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parser/ParserInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parser/ParserInterface.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parser/ParserInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parser/ParserMemory.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parser/ParserMemory.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Parser/ParserMemory.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Parser/ParserMemory.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Part.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Part.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/Part.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/Part.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/PartCollection.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/PartCollection.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Mime/PartCollection.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Mime/PartCollection.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Enumerations/ConnectionSecurityType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/ConnectionException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/ConnectionException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/ConnectionException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/ConnectionException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/InvalidArgumentException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/InvalidArgumentException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/InvalidArgumentException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/InvalidArgumentException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketAlreadyConnectedException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketAlreadyConnectedException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketAlreadyConnectedException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketAlreadyConnectedException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketCanNotConnectToHostException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketCanNotConnectToHostException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketCanNotConnectToHostException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketCanNotConnectToHostException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketConnectionDoesNotAvailableException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketReadException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketReadException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketReadException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketReadException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketReadTimeoutException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketReadTimeoutException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketReadTimeoutException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketReadTimeoutException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketUnreadBufferException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketUnreadBufferException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketUnreadBufferException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketUnreadBufferException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketUnsuppoterdSecureConnectionException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketUnsuppoterdSecureConnectionException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketUnsuppoterdSecureConnectionException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketUnsuppoterdSecureConnectionException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketWriteException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketWriteException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/Exceptions/SocketWriteException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/Exceptions/SocketWriteException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Net/NetClient.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Net/NetClient.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Net/NetClient.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Net/NetClient.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/LoginBadCredentialsException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/LoginBadCredentialsException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/LoginBadCredentialsException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/LoginBadCredentialsException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/NegativeResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/NegativeResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/NegativeResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/NegativeResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/ResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/ResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/ResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/ResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Exceptions/RuntimeException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Pop3Client.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Pop3Client.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Pop3/Pop3Client.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Pop3/Pop3Client.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/LoginBadCredentialsException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/LoginBadCredentialsException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/LoginBadCredentialsException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/LoginBadCredentialsException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/NegativeResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/NegativeResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/NegativeResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/NegativeResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/ResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/ResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/ResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/ResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/Exceptions/RuntimeException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/PoppassdClient.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/PoppassdClient.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Poppassd/PoppassdClient.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Poppassd/PoppassdClient.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/LoginBadCredentialsException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/LoginBadCredentialsException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/LoginBadCredentialsException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/LoginBadCredentialsException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/LoginBadMethodException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/LoginBadMethodException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/LoginBadMethodException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/LoginBadMethodException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/LoginException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/LoginException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/LoginException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/LoginException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/NegativeResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/NegativeResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/NegativeResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/NegativeResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/ResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/ResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/ResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/ResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/Exceptions/RuntimeException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/ManageSieveClient.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/ManageSieveClient.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Sieve/ManageSieveClient.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Sieve/ManageSieveClient.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/LoginBadCredentialsException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/LoginBadCredentialsException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/LoginBadCredentialsException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/LoginBadCredentialsException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/LoginBadMethodException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/LoginBadMethodException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/LoginBadMethodException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/LoginBadMethodException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/LoginException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/LoginException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/LoginException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/LoginException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/NegativeResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/NegativeResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/NegativeResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/NegativeResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/ResponseException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/ResponseException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/ResponseException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/ResponseException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/Exceptions/RuntimeException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/SmtpClient.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/SmtpClient.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Smtp/SmtpClient.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Smtp/SmtpClient.php diff --git a/rainloop/v/1.3.9.485/app/libraries/MailSo/Version.php b/rainloop/v/1.3.10.490/app/libraries/MailSo/Version.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/MailSo/Version.php rename to rainloop/v/1.3.10.490/app/libraries/MailSo/Version.php diff --git a/rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/Client.php b/rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/Client.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/Client.php rename to rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/Client.php diff --git a/rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php b/rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php rename to rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php diff --git a/rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/ClientCredentials.php b/rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/ClientCredentials.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/ClientCredentials.php rename to rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/ClientCredentials.php diff --git a/rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/IGrantType.php b/rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/IGrantType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/IGrantType.php rename to rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/IGrantType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/Password.php b/rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/Password.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/Password.php rename to rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/Password.php diff --git a/rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/RefreshToken.php b/rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/RefreshToken.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/GrantType/RefreshToken.php rename to rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/GrantType/RefreshToken.php diff --git a/rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/README b/rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/README similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/PHP-OAuth2/README rename to rainloop/v/1.3.10.490/app/libraries/PHP-OAuth2/README diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Account.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Account.php similarity index 98% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Account.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Account.php index ccba363c89..04d1ce09d7 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Account.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Account.php @@ -175,7 +175,7 @@ public function GetAuthToken() '0', // PasswordIsXOAuth2 $this->sSignMeToken, $this->sParentEmail, - \microtime(true).\rand(1000, 9999) + \RainLoop\Utils::GetShortToken() )); } } diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Actions.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Actions.php similarity index 94% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Actions.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Actions.php index ee4c2c0187..851628e23f 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Actions.php @@ -315,29 +315,20 @@ private function compileLogFileName() return $sFileName; } - private function generateSpecAuthKey() - { - return 'Account/SpecAuthToken/'.$this->GetSpecAuthToken().'/'.\RainLoop\Utils::GetConnectionToken().'/'.self::AUTH_TOKEN_KEY.'/'; - } - /** * @param \RainLoop\Account $oAccount - * @param bool $bRandomToken = false * * @return void */ - public function SetAuthToken($oAccount, $bRandomToken = false) + public function SetAuthToken($oAccount) { if ($oAccount) { - $sSpecAuthToken = '_'.\md5(APP_SALT.\RainLoop\Utils::GetConnectionToken().$oAccount->Email(). - ($bRandomToken ? microtime(true).rand(1000, 9999) : '').APP_SALT); + $sSpecAuthToken = '_'.$oAccount->GetAuthToken(); $this->SetSpecAuthToken($sSpecAuthToken); - $this->CacherFile()->Set($this->generateSpecAuthKey(), $oAccount->GetAuthToken()); - \RainLoop\Utils::SetCookie(self::AUTH_SPEC_TOKEN_KEY, $sSpecAuthToken, 0, '/', null, null, true); - + if ($oAccount->SignMe() && 0 < \strlen($oAccount->SignMeToken())) { \RainLoop\Utils::SetCookie(self::AUTH_SIGN_ME_TOKEN_KEY, $oAccount->SignMeToken(), @@ -378,7 +369,8 @@ private function setAdminAuthToken($sToken) */ private function getAuthToken() { - return $this->CacherFile()->Get($this->generateSpecAuthKey()); + $sToken = $this->GetSpecAuthToken(); + return $sToken && '_' === \substr($sToken, 0, 1) ? \substr($sToken, 1) : ''; } /** @@ -389,14 +381,6 @@ private function getAdminAuthToken() return \RainLoop\Utils::GetCookie(self::AUTH_ADMIN_TOKEN_KEY, ''); } - /** - * @return void - */ - public function ClearAuthToken() - { - $this->CacherFile()->Delete($this->generateSpecAuthKey()); - } - /** * @return void */ @@ -723,7 +707,7 @@ public function Logger() if (!@is_dir($sLogFileDir)) { - @mkdir($sLogFileDir, 0777, true); + @mkdir($sLogFileDir, 0755, true); } $this->oLogger->Add(\MailSo\Log\Drivers\File::NewInstance($sLogFileFullPath) @@ -738,8 +722,10 @@ public function Logger() $oHttp = $this->Http(); $this->oLogger->Write( - $oHttp->GetMethod().': '.$oHttp->GetHost().$oHttp->GetServer('REQUEST_URI', ''), + $oHttp->GetMethod().': '.$oHttp->GetHost(false, false).$oHttp->GetServer('REQUEST_URI', ''), \MailSo\Log\Enumerations\Type::NOTE, 'REQUEST'); + + $this->oLogger->Write('[PHP:'.PHP_VERSION.'][RL:'.APP_VERSION.']'); } } @@ -786,17 +772,19 @@ public function IsAdminLoggined($bThrowExceptionOnFalse = true) /** * @param string $sToken * @param bool $bThrowExceptionOnFalse = true + * @param bool $bValidateShortToken = true * * @return \RainLoop\Account|bool * @throws \RainLoop\Exceptions\ClientException */ - public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true) + public function GetAccountFromCustomToken($sToken, $bThrowExceptionOnFalse = true, $bValidateShortToken = true) { $oResult = false; if (!empty($sToken)) { $aAccountHash = \RainLoop\Utils::DecodeKeyValues($sToken); - if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && 8 === \count($aAccountHash)) + if (!empty($aAccountHash[0]) && 'token' === $aAccountHash[0] && 8 === \count($aAccountHash) && !empty($aAccountHash[7]) && + (!$bValidateShortToken || \RainLoop\Utils::GetShortToken() === $aAccountHash[7])) { $oAccount = $this->LoginProvider()->Provide( $aAccountHash[1], $aAccountHash[2], $aAccountHash[3], empty($aAccountHash[5]) ? '' : $aAccountHash[5]); @@ -857,11 +845,11 @@ private function getAccountFromToken($bThrowExceptionOnFalse = true) */ public function AppData($bAdmin, $sAuthAccountHash = '') { - if (0 < \strlen($sAuthAccountHash) && \preg_match('/[^_a-zA-Z0-9]/', $sAuthAccountHash)) + if (0 < \strlen($sAuthAccountHash) && \preg_match('/[^_\-\.a-zA-Z0-9]/', $sAuthAccountHash)) { $sAuthAccountHash = ''; } - + $oConfig = $this->Config(); $aResult = array( @@ -878,6 +866,7 @@ public function AppData($bAdmin, $sAuthAccountHash = '') 'CustomLoginLink' => $oConfig->Get('labs', 'custom_login_link', ''), 'CustomLogoutLink' => $oConfig->Get('labs', 'custom_logout_link', ''), 'AllowAdditionalAccounts' => (bool) $oConfig->Get('webmail', 'allow_additional_accounts', true), + 'AllowIdentities' => (bool) $oConfig->Get('webmail', 'allow_identities', true), 'DetermineUserLanguage' => (bool) $oConfig->Get('labs', 'determine_user_language', false), 'AllowCustomLogin' => (bool) $oConfig->Get('login', 'allow_custom_login', false), 'LoginDefaultDomain' => $oConfig->Get('login', 'default_domain', ''), @@ -1044,6 +1033,10 @@ public function AppData($bAdmin, $sAuthAccountHash = '') $aResult['ParentEmail'] = $oAccount->ParentEmail(); } + + $aResult['InterfaceAnimation'] = \RainLoop\Enumerations\InterfaceAnimation::NONE === $aResult['InterfaceAnimation'] + ? $aResult['InterfaceAnimation'] : \RainLoop\Enumerations\InterfaceAnimation::NORMAL; + if (!in_array($aResult['CustomThemeType'], array( \RainLoop\Enumerations\CustomThemeType::LIGHT, \RainLoop\Enumerations\CustomThemeType::DARK ))) @@ -1145,11 +1138,10 @@ private function loginErrorDelay() } /** * @param \RainLoop\Account $oAccount - * @param bool $bRandomToken = false */ - public function AuthProcess($oAccount, $bRandomToken = false) + public function AuthProcess($oAccount) { - $this->SetAuthToken($oAccount, $bRandomToken); + $this->SetAuthToken($oAccount); if ($oAccount instanceof \RainLoop\Account) { @@ -1173,10 +1165,7 @@ public function AuthProcess($oAccount, $bRandomToken = false) */ public function LoginProcess($sEmail, $sLogin, $sPassword, $sSignMeToken = '') { - $sSpecAuthToken = '_'.\md5(APP_SALT.\RainLoop\Utils::GetConnectionToken().$sEmail.APP_SALT); - $this->SetSpecAuthToken($sSpecAuthToken); - - $this->Plugins()->RunHook('filter.login-params', array(&$sEmail, &$sLogin, &$sPassword)); + $this->Plugins()->RunHook('filter.login-credentials', array(&$sEmail, &$sLogin, &$sPassword)); $oAccount = $this->LoginProvider()->Provide($sEmail, $sLogin, $sPassword, $sSignMeToken); if (!($oAccount instanceof \RainLoop\Account)) @@ -1226,7 +1215,7 @@ public function LoginProcess($sEmail, $sLogin, $sPassword, $sSignMeToken = '') $this->loginErrorDelay(); throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::AuthError, $oException); } - + return $oAccount; } @@ -1284,7 +1273,7 @@ public function DoLogin() */ public function GetAccounts($oAccount) { - $sParentEmail = 0 < \strlen($oAccount->ParentEmail()) ? $oAccount->ParentEmail() : $oAccount->Email(); + $sParentEmail = $oAccount->ParentEmailHelper(); $sAccounts = $this->StorageProvider()->Get(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, 'Webmail/Accounts/'.$sParentEmail.'/Array', null); @@ -1305,6 +1294,54 @@ public function GetAccounts($oAccount) return $aAccounts; } + /** + * @param \RainLoop\Account $oAccount + * + * @return array + */ + public function GetIdentities($oAccount) + { + $aIdentities = array(); + if ($oAccount) + { + $aSubIdentities = array(); + $oSettings = $this->SettingsProvider()->Load($oAccount); + if ($oSettings) + { + $sData = $oSettings->GetConf('Identities', ''); + if ('' !== $sData && '[' === \substr($sData, 0, 1)) + { + $aSubIdentities = @\json_decode($sData, true); + $aSubIdentities = \is_array($aSubIdentities) ? $aSubIdentities : array(); + } + } + + if (0 < \count($aSubIdentities)) + { + foreach ($aSubIdentities as $aItem) + { + if (isset($aItem['Id'], $aItem['Email'], $aItem['Name'], $aItem['ReplyTo'], $aItem['Bcc'])) + { + $oItem = \RainLoop\Identity::NewInstance($aItem['Id'], $aItem['Email'], + $aItem['Name'], $aItem['ReplyTo'], $aItem['Bcc']); + + $aIdentities[] = $oItem; + } + } + } + + if (0 === \count($aIdentities)) + { + $aIdentities[] = \RainLoop\Identity::NewInstance($oAccount->Email(), $oAccount->Email(), + $oSettings->GetConf('DisplayName', ''), + $oSettings->GetConf('ReplyTo', '') + ); + } + } + + return $aIdentities; + } + /** * @param \RainLoop\Account $oAccount * @param array $aAccounts = array() @@ -1313,7 +1350,7 @@ public function GetAccounts($oAccount) */ public function SetAccounts($oAccount, $aAccounts = array()) { - $sParentEmail = 0 < \strlen($oAccount->ParentEmail()) ? $oAccount->ParentEmail() : $oAccount->Email(); + $sParentEmail = $oAccount->ParentEmailHelper(); if (!\is_array($aAccounts) || 0 === \count($aAccounts)) { $this->StorageProvider()->Clear(null, \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, @@ -1326,6 +1363,30 @@ public function SetAccounts($oAccount, $aAccounts = array()) } } + /** + * @param \RainLoop\Account $oAccount + * @param array $aIdentities = array() + * + * @return array + */ + public function SetIdentities($oAccount, $aIdentities = array()) + { + $oSettings = $this->SettingsProvider()->Load($oAccount); + if ($oSettings) + { + $aResult = array(); + foreach ($aIdentities as $oItem) + { + $aResult[] = $oItem->ToSimpleJSON(); + } + + $oSettings->SetConf('Identities', @\json_encode($aResult)); + return $this->SettingsProvider()->Save($oAccount, $oSettings); + } + + return false; + } + /** * @return array * @@ -1333,13 +1394,13 @@ public function SetAccounts($oAccount, $aAccounts = array()) */ public function DoAccountAdd() { - $oAccount = $this->getAccountFromToken(); - if (!$this->Config()->Get('webmail', 'allow_additional_accounts', true)) { return $this->FalseResponse(__FUNCTION__); } + $oAccount = $this->getAccountFromToken(); + $sEmail = \trim($this->GetActionParam('Email', '')); $sLogin = \trim($this->GetActionParam('Login', '')); $sPassword = $this->GetActionParam('Password', ''); @@ -1395,13 +1456,13 @@ public function DoAccountAdd() */ public function DoAccountDelete() { - $oAccount = $this->getAccountFromToken(); - if (!$this->Config()->Get('webmail', 'allow_additional_accounts', true)) { return $this->FalseResponse(__FUNCTION__); } + $oAccount = $this->getAccountFromToken(); + $sParentEmail = 0 < \strlen($oAccount->ParentEmail()) ? $oAccount->ParentEmail() : $oAccount->Email(); $sEmailToDelete = \strtolower(\trim($this->GetActionParam('EmailToDelete', ''))); @@ -1422,25 +1483,140 @@ public function DoAccountDelete() return $this->FalseResponse(__FUNCTION__); } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoIdentityUpdate() + { + if (!$this->Config()->Get('webmail', 'allow_identities', true)) + { + return $this->FalseResponse(__FUNCTION__); + } + + $oAccount = $this->getAccountFromToken(); + + $sId = \trim($this->GetActionParam('Id', '')); + $sEmail = \trim($this->GetActionParam('Email', '')); + $sName = \trim($this->GetActionParam('Name', '')); + $sReplyTo = \trim($this->GetActionParam('ReplyTo', '')); + $sBcc = \trim($this->GetActionParam('Bcc', '')); + + if ($sId === $oAccount->Email()) + { + $sEmail = $oAccount->Email(); + + $oSettings = $this->SettingsProvider()->Load($oAccount); + if ($oSettings) + { + $oSettings->SetConf('DisplayName', $sName); + $oSettings->SetConf('ReplyTo', $sReplyTo); + + $this->SettingsProvider()->Save($oAccount, $oSettings); + } + } + + if (empty($sEmail)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); + } + + $oEditIdentity = null; + $aIdentities = $this->GetIdentities($oAccount); + if (0 < \strlen($sId)) + { + foreach ($aIdentities as &$oItem) + { + if ($oItem && $sId === $oItem->Id()) + { + $oEditIdentity =& $oItem; + break; + } + } + } + else + { + $sId = \md5($sEmail.\microtime(true)); + } + + if (!$oEditIdentity) + { + $aIdentities[] = \RainLoop\Identity::NewInstance($sId, $sEmail, $sName, $sReplyTo, $sBcc); + } + else + { + $oEditIdentity + ->SetEmail($sEmail) + ->SetName($sName) + ->SetReplyTo($sReplyTo) + ->SetBcc($sBcc) + ; + } + + return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aIdentities)); + } + + /** + * @return array + * + * @throws \MailSo\Base\Exceptions\Exception + */ + public function DoIdentityDelete() + { + if (!$this->Config()->Get('webmail', 'allow_identities', true)) + { + return $this->FalseResponse(__FUNCTION__); + } + + $oAccount = $this->getAccountFromToken(); + + $sId = \trim($this->GetActionParam('IdToDelete', '')); + if (empty($sId) || $sId === $oAccount->Email()) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); + } + + $aNew = array(); + $aIdentities = $this->GetIdentities($oAccount); + foreach ($aIdentities as $oItem) + { + if ($oItem && $sId !== $oItem->Id()) + { + $aNew[] = $oItem; + } + } + + return $this->DefaultResponse(__FUNCTION__, $this->SetIdentities($oAccount, $aNew)); + } /** * @return array * * @throws \MailSo\Base\Exceptions\Exception */ - public function DoAccounts() + public function DoAccountsAndIdentities() { $oAccount = $this->getAccountFromToken(); + $mAccounts = false; if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) { - $aAccounts = $this->GetAccounts($oAccount); - $aAccounts = \array_keys($aAccounts); + $mAccounts = $this->GetAccounts($oAccount); + $mAccounts = \array_keys($mAccounts); + } - return $this->DefaultResponse(__FUNCTION__, $aAccounts); + $mIdentities = false; + if ($this->Config()->Get('webmail', 'allow_identities', true)) + { + $mIdentities = $this->GetIdentities($oAccount); } - return $this->FalseResponse(__FUNCTION__); + return $this->DefaultResponse(__FUNCTION__, array( + 'Accounts' => $mAccounts, + 'Identities' => $mIdentities + )); } /** @@ -1458,8 +1634,6 @@ public function DoLogout() 'SignMe/UserToken/'.$oAccount->SignMeToken()); } - $this->ClearAuthToken(); - return $this->TrueResponse(__FUNCTION__); } @@ -1468,8 +1642,6 @@ public function DoLogout() */ public function DoAppDelayStart() { -// $oAccount = $this->getAccountFromToken(); - \RainLoop\Utils::UpdateConnectionToken(); $bUserCache = false; @@ -1649,6 +1821,8 @@ public function DoAdminSettingsUpdate() $this->setConfigFromParams($oConfig, 'LoginDefaultDomain', 'login', 'default_domain', 'string'); $this->setConfigFromParams($oConfig, 'AllowAdditionalAccounts', 'webmail', 'allow_additional_accounts', 'bool'); + $this->setConfigFromParams($oConfig, 'AllowIdentities', 'webmail', 'allow_identities', 'bool'); + $this->setConfigFromParams($oConfig, 'DetermineUserLanguage', 'labs', 'determine_user_language', 'bool'); $this->setConfigFromParams($oConfig, 'Title', 'webmail', 'title', 'string'); @@ -2038,7 +2212,9 @@ private function rainloopRepo($bAdditionalOnly = false) private function rainLoopUpdatable() { - return @file_exists(APP_INDEX_ROOT_PATH.'index.php') && @is_writable(APP_INDEX_ROOT_PATH.'index.php'); + return @file_exists(APP_INDEX_ROOT_PATH.'index.php') && + @is_writable(APP_INDEX_ROOT_PATH.'index.php') && + @is_writable(APP_INDEX_ROOT_PATH.'rainloop/'); } private function rainLoopCoreAccess() @@ -2152,7 +2328,7 @@ private function getRepositoryData(&$bReal, &$bRainLoopUpdatable) { $bRainLoopUpdatable = $this->rainLoopUpdatable(); $bCoreAccess = $this->rainLoopCoreAccess(); - + $aResult = $this->getRepositoryDataByUrl($this->rainloopRepo(), $bReal); $sAddRepo = $this->rainloopRepo(true); @@ -2230,9 +2406,11 @@ private function getRepositoryData(&$bReal, &$bRainLoopUpdatable) $aItem['compare'] = \version_compare($aItem['installed'], $aItem['version'], '<'); $aItem['canBeDeleted'] = '' !== $aItem['installed'] && 'plugin' === $aItem['type']; $aItem['canBeUpdated'] = $aItem['compare']; + $aItem['canBeInstalled'] = true; if (!$bRainLoopUpdatable && 'plugin' !== $aItem['type']) { + $aItem['canBeInstalled'] = false; $aItem['canBeUpdated'] = false; $aItem['compare'] = false; } @@ -2325,7 +2503,7 @@ public function DoAdminPackageInstall() } } } - + $sTmp = ''; $bResult = false; if ('' !== $sRealFile) @@ -2338,6 +2516,8 @@ public function DoAdminPackageInstall() $iCode = 0; $sContentType = ''; + @\set_time_limit(60); + $oHttp = \MailSo\Base\Http::SingletonInstance(); $bResult = $oHttp->SaveUrlToFile($sUrl, $pDest, $sTmp, $sContentType, $iCode, $this->Logger(), 60); if (!$bResult) @@ -2379,12 +2559,23 @@ public function DoAdminPackageInstall() file_exists($sTmpFolder.'/data/VERSION') && is_dir($sTmpFolder.'/rainloop/')) { - \MailSo\Base\Utils::CopyDir($sTmpFolder.'/rainloop/', APP_INDEX_ROOT_PATH.'rainloop/'); - - copy($sTmpFolder.'/data/VERSION', APP_DATA_FOLDER_PATH.'VERSION'); - copy($sTmpFolder.'/index.php', APP_INDEX_ROOT_PATH.'index.php'); + $sNewVersion = file_get_contents($sTmpFolder.'/data/VERSION'); + if ($sNewVersion && !is_dir(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion)) + { + \MailSo\Base\Utils::CopyDir($sTmpFolder.'/rainloop/', APP_INDEX_ROOT_PATH.'rainloop/'); + + copy($sTmpFolder.'/data/VERSION', APP_DATA_FOLDER_PATH.'VERSION'); + if (md5_file($sTmpFolder.'/index.php') !== md5_file(APP_INDEX_ROOT_PATH.'index.php')) + { + copy($sTmpFolder.'/index.php', APP_INDEX_ROOT_PATH.'index.php'); + } - $bResult = true; + $bResult = true; + } + else + { + $this->Logger()->WriteDump($sNewVersion.' version already installed', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } } else if ($bResult) { @@ -2393,6 +2584,10 @@ public function DoAdminPackageInstall() \MailSo\Base\Utils::RecRmDir($sTmpFolder); } + else + { + $this->Logger()->Write('Cannot create tmp folder: '.$sTmpFolder, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER'); + } } else { @@ -2760,16 +2955,18 @@ public function DoJsError() if (0 < strlen($sMessage)) { $sFileName = $this->GetActionParam('FileName', ''); - $iLineNo = $this->GetActionParam('LineNo', ''); + $sLineNo = $this->GetActionParam('LineNo', ''); $sLocation = $this->GetActionParam('Location', ''); $sHtmlCapa = $this->GetActionParam('HtmlCapa', ''); + $sTimeOnPage = $this->GetActionParam('TimeOnPage', ''); $oHttp = $this->Http(); - $this->Logger()->Write($sMessage.' ('.$sFileName.' ~ '.$iLineNo.')', \MailSo\Log\Enumerations\Type::ERROR, 'JS'); + $this->Logger()->Write($sMessage.' ('.$sFileName.' ~ '.$sLineNo.')', \MailSo\Log\Enumerations\Type::ERROR, 'JS'); $this->Logger()->WriteDump(array( 'Location' => $sLocation, 'Capability' => $sHtmlCapa, + 'TimeOnPage' => $sTimeOnPage, 'HTTP_USER_AGENT' => $oHttp->GetServer('HTTP_USER_AGENT', ''), 'HTTP_ACCEPT_ENCODING' => $oHttp->GetServer('HTTP_ACCEPT_ENCODING', ''), 'HTTP_ACCEPT_LANGUAGE' => $oHttp->GetServer('HTTP_ACCEPT_LANGUAGE', '') @@ -3095,6 +3292,11 @@ public function DoFolderInformation() throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::MailServerError, $oException); } + if (\is_array($aInboxInformation)) + { + $aInboxInformation['Version'] = APP_VERSION; + } + return $this->DefaultResponse(__FUNCTION__, $aInboxInformation); } @@ -3200,6 +3402,7 @@ public function DoMessageList() */ private function buildMessage($oAccount, $bWithDraftInfo = true, $sMessageID = '') { + $sFrom = $this->GetActionParam('From', ''); $sTo = $this->GetActionParam('To', ''); $sCc = $this->GetActionParam('Cc', ''); $sBcc = $this->GetActionParam('Bcc', ''); @@ -3225,22 +3428,29 @@ private function buildMessage($oAccount, $bWithDraftInfo = true, $sMessageID = ' $oMessage->SetXMailer('RainLoop/'.APP_VERSION); $oSettings = $this->SettingsProvider()->Load($oAccount); - $sDisplayName = \trim($oSettings->GetConf('DisplayName', '')); - $sReplyTo = \trim($oSettings->GetConf('ReplyTo', '')); - - $oMessage - ->SetFrom(\MailSo\Mime\Email::NewInstance($oAccount->Email(), $sDisplayName)) - ->SetSubject($sSubject) - ; - if (!empty($sReplyTo)) + if ($this->Config()->Get('webmail', 'allow_identities', true)) + { + $oMessage->SetFrom(\MailSo\Mime\Email::Parse($sFrom)); + } + else { - $oReplyTo = \MailSo\Mime\EmailCollection::NewInstance($sReplyTo); - if ($oReplyTo && $oReplyTo->Count()) + $sDisplayName = \trim($oSettings->GetConf('DisplayName', '')); + $sReplyTo = \trim($oSettings->GetConf('ReplyTo', '')); + + $oMessage->SetFrom(\MailSo\Mime\Email::NewInstance($oAccount->Email(), $sDisplayName)); + + if (!empty($sReplyTo)) { - $oMessage->SetReplyTo($oReplyTo); + $oReplyTo = \MailSo\Mime\EmailCollection::NewInstance($sReplyTo); + if ($oReplyTo && $oReplyTo->Count()) + { + $oMessage->SetReplyTo($oReplyTo); + } } } + + $oMessage->SetSubject($sSubject); $oToEmails = \MailSo\Mime\EmailCollection::NewInstance($sTo); if ($oToEmails && $oToEmails->Count()) @@ -3437,27 +3647,42 @@ public function DoSendMessage() $oRcpt = $oMessage->GetRcpt(); if ($oRcpt && 0 < $oRcpt->Count()) { + $this->Plugins()->RunHook('filter.message-rcpt', array($oAccount, &$oRcpt)); + try { - $sHostName = \function_exists('gethostname') ? \gethostname() : 'localhost'; - $oSmtpClient = \MailSo\Smtp\SmtpClient::NewInstance()->SetLogger($this->Logger()); - $oSmtpClient->Connect($oAccount->Domain()->OutHost(), $oAccount->Domain()->OutPort(), - $sHostName, $oAccount->Domain()->OutSecure()); + $aSmtpCredentials = array( + 'Ehlo' => \function_exists('gethostname') ? \gethostname() : 'localhost', + 'Host' => $oAccount->Domain()->OutHost(), + 'Port' => $oAccount->Domain()->OutPort(), + 'Secure' => $oAccount->Domain()->OutSecure(), + 'UseAuth' => $oAccount->Domain()->OutAuth(), + 'From' => $oAccount->Email(), + 'Login' => $oAccount->Login(), + 'Password' => $oAccount->Password(), + 'UseShortLogin' => $oAccount->Domain()->OutShortLogin(), + 'HiddenRcpt' => array() + ); - if ($oAccount->Domain()->OutAuth()) + $this->Plugins()->RunHook('filter.smtp-credentials', array($oAccount, &$aSmtpCredentials)); + + $oSmtpClient->Connect($aSmtpCredentials['Host'], $aSmtpCredentials['Port'], + $aSmtpCredentials['Ehlo'], $aSmtpCredentials['Secure']); + + if ($aSmtpCredentials['UseAuth']) { - $sLogin = $oAccount->Login(); - if ($oAccount->Domain()->OutShortLogin()) + $sLogin = $aSmtpCredentials['Login']; + if ($aSmtpCredentials['UseShortLogin']) { $sLogin = \MailSo\Base\Utils::GetAccountNameFromEmail($sLogin); } - $oSmtpClient->Login($sLogin, $oAccount->Password()); + $oSmtpClient->Login($sLogin, $aSmtpCredentials['Password']); } - $oSmtpClient->MailFrom($oAccount->Email()); + $oSmtpClient->MailFrom($aSmtpCredentials['From']); $aRcpt =& $oRcpt->GetAsArray(); foreach ($aRcpt as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) @@ -3465,6 +3690,17 @@ public function DoSendMessage() $oSmtpClient->Rcpt($oEmail->GetEmail()); } + if (isset($aSmtpCredentials['HiddenRcpt']) && is_array($aSmtpCredentials['HiddenRcpt'])) + { + foreach ($aSmtpCredentials['HiddenRcpt'] as $sEmail) + { + if (\preg_match('/^[^@\s]+@[^@\s]+$/', $sEmail)) + { + $oSmtpClient->Rcpt($sEmail); + } + } + } + $oSmtpClient->DataWithStream($rMessageStream); $oSmtpClient->LogoutAndDisconnect(); @@ -4888,7 +5124,7 @@ private function setupInformation() 'pdo-sqlite' => \is_array($mPdoDrivers) ? \in_array('sqlite', $mPdoDrivers) : false, 'pdo-mysql' => \is_array($mPdoDrivers) ? \in_array('mysql', $mPdoDrivers) : false ), - 'php' => \phpversion() + 'php' => PHP_VERSION ); $aResult['domains'] = $this->DomainProvider()->Count(); @@ -5273,7 +5509,13 @@ protected function responseObject($mResponse, $sParent = '', $aParameters = arra { $bHook = true; $sClassName = \get_class($mResponse); - if ('MailSo\Mail\Message' === $sClassName) + $bHasSimpleJsonFunc = \method_exists($mResponse, 'ToSimpleJSON'); + + if ($bHasSimpleJsonFunc) + { + $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), $mResponse->ToSimpleJSON()); + } + else if ('MailSo\Mail\Message' === $sClassName) { $oAccount = $this->getAccountFromToken(false); @@ -5418,22 +5660,6 @@ protected function responseObject($mResponse, $sParent = '', $aParameters = arra 'Emails' => $mResponse->Emails )); } - else if ('RainLoop\Domain' === $sClassName) - { - $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array( - 'Name' => $mResponse->Name(), - 'IncHost' => $mResponse->IncHost(), - 'IncPort' => $mResponse->IncPort(), - 'IncSecure' => $mResponse->IncSecure(), - 'IncShortLogin' => $mResponse->IncShortLogin(), - 'OutHost' => $mResponse->OutHost(), - 'OutPort' => $mResponse->OutPort(), - 'OutSecure' => $mResponse->OutSecure(), - 'OutShortLogin' => $mResponse->OutShortLogin(), - 'OutAuth' => $mResponse->OutAuth(), - 'WhiteList' => $mResponse->WhiteList() - )); - } else if ('MailSo\Mail\Attachment' === $sClassName) { $oAccount = $this->getAccountFromToken(false); @@ -5539,8 +5765,6 @@ protected function responseObject($mResponse, $sParent = '', $aParameters = arra 'IsThreadsSupported' => $mResponse->IsThreadsSupported, 'SystemFolders' => isset($mResponse->SystemFolders) && \is_array($mResponse->SystemFolders) ? $mResponse->SystemFolders : array() )); - - } else if ($mResponse instanceof \MailSo\Base\Collection) { diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Config/AbstractConfig.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Config/AbstractConfig.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Config/AbstractConfig.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Config/AbstractConfig.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Config/Application.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Config/Application.php similarity index 96% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Config/Application.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Config/Application.php index 51d1de4942..634d22abd0 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Config/Application.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Config/Application.php @@ -1,223 +1,224 @@ -Set('security', 'admin_password', \md5(APP_SALT.$sPassword.APP_SALT)); - } - - /** - * @param string $sPassword - * - * @return bool - */ - public function ValidatePassword($sPassword) - { - $sPassword = (string) $sPassword; - $sConfigPassword = (string) $this->Get('security', 'admin_password', ''); - - return 0 < \strlen($sPassword) && - ($sPassword === $sConfigPassword || \md5(APP_SALT.$sPassword.APP_SALT) === $sConfigPassword); - } - - /** - * @return bool - */ - public function Save() - { - $this->Set('version', 'current', APP_VERSION); - $this->Set('version', 'saved', \gmdate('r')); - - return parent::Save(); - } - - /** - * @return array - */ - protected function defaultValues() - { - return array( - 'webmail' => array( - - 'title' => array('RainLoop Webmail', 'Text displayed as page title'), - - 'theme' => array('Default', 'Theme used by default'), - 'allow_themes' => array(true, 'Allow theme selection on settings screen'), - 'allow_custom_theme' => array(true, ''), - - 'language' => array('en', 'Language used by default'), - 'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'), - - 'allow_additional_accounts' => array(true, ''), - - 'use_preview_pane' => array(true, 'Whether message preview pane should be used'), - - 'messages_per_page' => array(20, ' Number of messages displayed on page by default'), - - 'editor_default_type' => array('Html', 'Editor mode used by default (Html or Plain)'), - - 'attachment_size_limit' => array(5, - 'File size limit (MB) for file upload on compose screen -0 for unlimited.') - ), - - 'security' => array( - 'csrf_protection' => array(true, - 'Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)'), - - 'custom_server_signature' => array('RainLoop'), - 'admin_login' => array('admin', 'Login and password for web admin panel'), - 'admin_password' => array('12345') - ), - - 'login' => array( - - 'allow_custom_login' => array(false, - 'Enable additional Login field on webmail login screen'), - - 'default_domain' => array('', ''), - - 'allow_languages_on_login' => array(true, - 'Allow language selection on webmail login screen'), - - 'sign_me_auto' => array(\RainLoop\Enumerations\SignMeType::DEFAILT_OFF, - 'This option allows webmail to remember the logged in user -once they closed the browser window. - -Values: - "DefaultOff" - can be used, disabled by default; - "DefaultOn" - can be used, enabled by default; - "Unused" - cannot be used') - ), - - 'plugins' => array( - 'enable' => array(false, 'Enable plugin support'), - 'enabled_list' => array('', 'List of enabled plugins'), - ), - - 'logs' => array( - - 'enable' => array(false, 'Enable logging'), - - 'write_on_error_only' => array(false, 'Logs entire request only if error occured'), - - 'filename' => array('log-{date:Y-m-d}.txt', - 'Log filename. -For security reasons, some characters are removed from filename. -Allows for pattern-based folder creation (see examples below). - -Patterns: - {date:Y-m-d} - Replaced by pattern-based date - Detailed info: http://www.php.net/manual/en/function.date.php - {user:email} - Replaced by user\'s email address - If user is not logged in, value is set to "unknown" - {user:login} - Replaced by user\'s login - If user is not logged in, value is set to "unknown" - {user:domain} - Replaced by user\'s domain name - If user is not logged in, value is set to "unknown" - {user:uid} - Replaced by user\'s UID regardless of account currently used - -Examples: - filename = "log-{date:Y-m-d}.txt" - filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log" - filename = "{user:email}-{date:Y-m-d}.txt"') - ), - - 'debug' => array( - 'enable' => array(false, 'Special option required for development purposes'), - ), - - 'version' => array( - 'current' => array(''), - 'saved' => array('') - ), - - 'social' => array( - 'google_enable' => array(false, 'Google'), - 'google_client_id' => array(''), - 'google_client_secret' => array(''), - - 'fb_enable' => array(false, 'Facebook'), - 'fb_app_id' => array(''), - 'fb_app_secret' => array(''), - - 'twitter_enable' => array(false, 'Twitter'), - 'twitter_consumer_key' => array(''), - 'twitter_consumer_secret' => array(''), - - 'dropbox_enable' => array(false, 'Dropbox'), - 'dropbox_api_key' => array(''), - ), - - 'cache' => array( - 'enable' => array(true, - 'The section controls caching of the entire application. - -Enables caching in the system'), - - 'index' => array('v1', 'Additional caching key. If changed, cache is purged'), - - 'fast_cache_driver' => array('files', 'Can be: files, APC, memcache'), - 'fast_cache_index' => array('v1', 'Additional caching key. If changed, fast cache is purged'), - - 'http' => array(true, 'Browser-level cache. If enabled, caching is maintainted without using files'), - 'server_uids' => array(false, 'Caching message UIDs when searching and sorting (threading)') - ), - - 'labs' => array( - 'ignore_folders_subscription' => array(false, - 'Experimental settings. Handle with care. -'), - 'allow_message_append' => array(false), - 'date_from_headers' => array(false), - 'cache_system_data' => array(true), - 'use_app_debug_js' => array(false), - 'use_app_debug_css' => array(false), - 'login_fault_delay' => array(1), - 'log_ajax_response_write_limit' => array(300), - 'suggestions_limit' => array(50), - 'determine_user_language' => array(false), - 'use_imap_sort' => array(false), - 'use_imap_list_status' => array(false), - 'use_imap_list_subscribe' => array(true), - 'use_imap_thread' => array(true), - 'use_imap_move' => array(true), - 'use_imap_auth_plain' => array(false), - 'custom_repo' => array(''), - 'additional_repo' => array(''), - 'cdn_static_domain' => array(''), - 'in_iframe' => array(false), - 'custom_login_link' => array(''), - 'custom_logout_link' => array(''), - 'allow_contacts' => array(true), - 'allow_external_login' => array(false), - 'allow_admin_panel' => array(true), - 'fast_cache_memcache_host' => array('127.0.0.1'), - 'fast_cache_memcache_port' => array(11211), - 'fast_cache_memcache_expire' => array(43200), - 'usage_statistics' => array(true), - 'dev_email' => array(''), - 'dev_login' => array(''), - 'dev_password' => array('') - ) - ); - } -} +Set('security', 'admin_password', \md5(APP_SALT.$sPassword.APP_SALT)); + } + + /** + * @param string $sPassword + * + * @return bool + */ + public function ValidatePassword($sPassword) + { + $sPassword = (string) $sPassword; + $sConfigPassword = (string) $this->Get('security', 'admin_password', ''); + + return 0 < \strlen($sPassword) && + ($sPassword === $sConfigPassword || \md5(APP_SALT.$sPassword.APP_SALT) === $sConfigPassword); + } + + /** + * @return bool + */ + public function Save() + { + $this->Set('version', 'current', APP_VERSION); + $this->Set('version', 'saved', \gmdate('r')); + + return parent::Save(); + } + + /** + * @return array + */ + protected function defaultValues() + { + return array( + 'webmail' => array( + + 'title' => array('RainLoop Webmail', 'Text displayed as page title'), + + 'theme' => array('Default', 'Theme used by default'), + 'allow_themes' => array(true, 'Allow theme selection on settings screen'), + 'allow_custom_theme' => array(true, ''), + + 'language' => array('en', 'Language used by default'), + 'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'), + + 'allow_additional_accounts' => array(true, ''), + 'allow_identities' => array(false, ''), + + 'use_preview_pane' => array(true, 'Whether message preview pane should be used'), + + 'messages_per_page' => array(20, ' Number of messages displayed on page by default'), + + 'editor_default_type' => array('Html', 'Editor mode used by default (Html or Plain)'), + + 'attachment_size_limit' => array(5, + 'File size limit (MB) for file upload on compose screen +0 for unlimited.') + ), + + 'security' => array( + 'csrf_protection' => array(true, + 'Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)'), + + 'custom_server_signature' => array('RainLoop'), + 'admin_login' => array('admin', 'Login and password for web admin panel'), + 'admin_password' => array('12345') + ), + + 'login' => array( + + 'allow_custom_login' => array(false, + 'Enable additional Login field on webmail login screen'), + + 'default_domain' => array('', ''), + + 'allow_languages_on_login' => array(true, + 'Allow language selection on webmail login screen'), + + 'sign_me_auto' => array(\RainLoop\Enumerations\SignMeType::DEFAILT_OFF, + 'This option allows webmail to remember the logged in user +once they closed the browser window. + +Values: + "DefaultOff" - can be used, disabled by default; + "DefaultOn" - can be used, enabled by default; + "Unused" - cannot be used') + ), + + 'plugins' => array( + 'enable' => array(false, 'Enable plugin support'), + 'enabled_list' => array('', 'List of enabled plugins'), + ), + + 'logs' => array( + + 'enable' => array(false, 'Enable logging'), + + 'write_on_error_only' => array(false, 'Logs entire request only if error occured'), + + 'filename' => array('log-{date:Y-m-d}.txt', + 'Log filename. +For security reasons, some characters are removed from filename. +Allows for pattern-based folder creation (see examples below). + +Patterns: + {date:Y-m-d} - Replaced by pattern-based date + Detailed info: http://www.php.net/manual/en/function.date.php + {user:email} - Replaced by user\'s email address + If user is not logged in, value is set to "unknown" + {user:login} - Replaced by user\'s login + If user is not logged in, value is set to "unknown" + {user:domain} - Replaced by user\'s domain name + If user is not logged in, value is set to "unknown" + {user:uid} - Replaced by user\'s UID regardless of account currently used + +Examples: + filename = "log-{date:Y-m-d}.txt" + filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log" + filename = "{user:email}-{date:Y-m-d}.txt"') + ), + + 'debug' => array( + 'enable' => array(false, 'Special option required for development purposes'), + ), + + 'version' => array( + 'current' => array(''), + 'saved' => array('') + ), + + 'social' => array( + 'google_enable' => array(false, 'Google'), + 'google_client_id' => array(''), + 'google_client_secret' => array(''), + + 'fb_enable' => array(false, 'Facebook'), + 'fb_app_id' => array(''), + 'fb_app_secret' => array(''), + + 'twitter_enable' => array(false, 'Twitter'), + 'twitter_consumer_key' => array(''), + 'twitter_consumer_secret' => array(''), + + 'dropbox_enable' => array(false, 'Dropbox'), + 'dropbox_api_key' => array(''), + ), + + 'cache' => array( + 'enable' => array(true, + 'The section controls caching of the entire application. + +Enables caching in the system'), + + 'index' => array('v1', 'Additional caching key. If changed, cache is purged'), + + 'fast_cache_driver' => array('files', 'Can be: files, APC, memcache'), + 'fast_cache_index' => array('v1', 'Additional caching key. If changed, fast cache is purged'), + + 'http' => array(true, 'Browser-level cache. If enabled, caching is maintainted without using files'), + 'server_uids' => array(false, 'Caching message UIDs when searching and sorting (threading)') + ), + + 'labs' => array( + 'ignore_folders_subscription' => array(false, + 'Experimental settings. Handle with care. +'), + 'allow_message_append' => array(false), + 'date_from_headers' => array(false), + 'cache_system_data' => array(true), + 'use_app_debug_js' => array(false), + 'use_app_debug_css' => array(false), + 'login_fault_delay' => array(1), + 'log_ajax_response_write_limit' => array(300), + 'suggestions_limit' => array(50), + 'determine_user_language' => array(true), + 'use_imap_sort' => array(false), + 'use_imap_list_status' => array(false), + 'use_imap_list_subscribe' => array(true), + 'use_imap_thread' => array(true), + 'use_imap_move' => array(true), + 'use_imap_auth_plain' => array(false), + 'custom_repo' => array(''), + 'additional_repo' => array(''), + 'cdn_static_domain' => array(''), + 'in_iframe' => array(false), + 'custom_login_link' => array(''), + 'custom_logout_link' => array(''), + 'allow_contacts' => array(true), + 'allow_external_login' => array(false), + 'allow_admin_panel' => array(true), + 'fast_cache_memcache_host' => array('127.0.0.1'), + 'fast_cache_memcache_port' => array(11211), + 'fast_cache_memcache_expire' => array(43200), + 'usage_statistics' => array(true), + 'dev_email' => array(''), + 'dev_login' => array(''), + 'dev_password' => array('') + ) + ); + } +} diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Config/Plugin.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Config/Plugin.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Config/Plugin.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Config/Plugin.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Domain.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Domain.php similarity index 94% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Domain.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Domain.php index b4017c7ef8..1a28ec8baa 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Domain.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Domain.php @@ -411,4 +411,24 @@ public function ValidateWhiteList($sEmail, $sLogin = '') return true; } + + /** + * @return array + */ + public function ToSimpleJSON() + { + return array( + 'Name' => $this->Name(), + 'IncHost' => $this->IncHost(), + 'IncPort' => $this->IncPort(), + 'IncSecure' => $this->IncSecure(), + 'IncShortLogin' => $this->IncShortLogin(), + 'OutHost' => $this->OutHost(), + 'OutPort' => $this->OutPort(), + 'OutSecure' => $this->OutSecure(), + 'OutShortLogin' => $this->OutShortLogin(), + 'OutAuth' => $this->OutAuth(), + 'WhiteList' => $this->WhiteList() + ); + } } diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/CustomThemeType.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/CustomThemeType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/CustomThemeType.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/CustomThemeType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/InterfaceAnimation.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/InterfaceAnimation.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/InterfaceAnimation.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/InterfaceAnimation.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/PluginPropertyType.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/PluginPropertyType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/PluginPropertyType.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/PluginPropertyType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/SignMeType.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/SignMeType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/SignMeType.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/SignMeType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/TimeFormat.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/TimeFormat.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Enumerations/TimeFormat.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Enumerations/TimeFormat.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/AuthException.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/AuthException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/AuthException.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/AuthException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/ClientException.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/ClientException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/ClientException.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/ClientException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/Exception.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/Exception.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/Exception.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/Exception.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/InvalidArgumentException.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/InvalidArgumentException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/InvalidArgumentException.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/InvalidArgumentException.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/RuntimeException.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/RuntimeException.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Exceptions/RuntimeException.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Exceptions/RuntimeException.php diff --git a/rainloop/v/1.3.10.490/app/libraries/RainLoop/Identity.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Identity.php new file mode 100644 index 0000000000..2adae80e23 --- /dev/null +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Identity.php @@ -0,0 +1,177 @@ +sId = $sId; + $this->sEmail = \strtolower($sEmail); + $this->sName = \trim($sName); + $this->sReplyTo = \trim($sReplyTo); + $this->sBcc = \trim($sBcc); + } + + /** + * @param string $sId + * @param string $sEmail + * @param string $sName = '' + * @param string $sReplyTo = '' + * @param string $sBcc = '' + * + * @return \RainLoop\Identity + */ + public static function NewInstance($sId, $sEmail, $sName = '', $sReplyTo = '', $sBcc = '') + { + return new self($sId, $sEmail, $sName, $sReplyTo, $sBcc); + } + + /** + * @return string + */ + public function Id() + { + return $this->sId; + } + + /** + * @param string $sId + * + * @return \RainLoop\Identity + */ + public function SetId($sId) + { + $this->sId = $sId; + + return $this; + } + + /** + * @return string + */ + public function Email() + { + return $this->sEmail; + } + + /** + * @param string $sEmail + * + * @return \RainLoop\Identity + */ + public function SetEmail($sEmail) + { + $this->sEmail = $sEmail; + + return $this; + } + + /** + * @return string + */ + public function Name() + { + return $this->sName; + } + + /** + * @param string $sName + * + * @return \RainLoop\Identity + */ + public function SetName($sName) + { + $this->sName = $sName; + + return $this; + } + + /** + * @return string + */ + public function ReplyTo() + { + return $this->sReplyTo; + } + + /** + * @param string $sReplyTo + * + * @return \RainLoop\Identity + */ + public function SetReplyTo($sReplyTo) + { + $this->sReplyTo = $sReplyTo; + + return $this; + } + + /** + * @return string + */ + public function Bcc() + { + return $this->sBcc; + } + + /** + * @param string $sBcc + * + * @return \RainLoop\Identity + */ + public function SetBcc($sBcc) + { + $this->sBcc = $sBcc; + + return $this; + } + + /** + * @return array + */ + public function ToSimpleJSON() + { + return array( + 'Id' => $this->Id(), + 'Email' => $this->Email(), + 'Name' => $this->Name(), + 'ReplyTo' => $this->ReplyTo(), + 'Bcc' => $this->Bcc() + ); + } +} diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Notifications.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Notifications.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Notifications.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Notifications.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Plugins/AbstractPlugin.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Plugins/AbstractPlugin.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Plugins/AbstractPlugin.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Plugins/AbstractPlugin.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Plugins/Manager.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Plugins/Manager.php similarity index 91% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Plugins/Manager.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Plugins/Manager.php index 930b88c54d..3595c09d0b 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Plugins/Manager.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Plugins/Manager.php @@ -157,19 +157,28 @@ public function CreatePluginByName($sName) public function InstalledPlugins() { $aList = array(); - - foreach (glob(APP_PLUGINS_PATH.'*', GLOB_ONLYDIR|GLOB_NOSORT) as $sPathName) + + $aGlob = @\glob(APP_PLUGINS_PATH.'*', GLOB_ONLYDIR|GLOB_NOSORT); + if (\is_array($aGlob)) { - $sName = basename($sPathName); - if (preg_match('/^[a-z0-9\-]+$/', $sName) && - file_exists($sPathName.'/index.php')) + foreach ($aGlob as $sPathName) { - $sVersion = @file_get_contents($sPathName.'/VERSION'); - $aList[] = array( - $sName, $sVersion - ); + $sName = \basename($sPathName); + if (\preg_match('/^[a-z0-9\-]+$/', $sName) && + \file_exists($sPathName.'/index.php')) + { + $sVersion = @\file_get_contents($sPathName.'/VERSION'); + $aList[] = array( + $sName, $sVersion + ); + } } } + else + { + $this->Actions()->Logger()->Write('Cannot get installed plugins from '.APP_PLUGINS_PATH, + \MailSo\Log\Enumerations\Type::ERROR); + } return $aList; } diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Plugins/Property.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Plugins/Property.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Plugins/Property.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Plugins/Property.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/AbstractProvider.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/AbstractProvider.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/AbstractProvider.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/AbstractProvider.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/ChangePassword.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/ChangePassword.php similarity index 94% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/ChangePassword.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/ChangePassword.php index 8e01e69eba..8530973052 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/ChangePassword.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/ChangePassword.php @@ -16,7 +16,7 @@ class ChangePassword extends \RainLoop\Providers\AbstractProvider /** * @param \RainLoop\Actions $oActions - * @param \RainLoop\Providers\Suggestions\SuggestionsInterface|null $oDriver = null + * @param \RainLoop\Providers\ChangePassword\ChangePasswordInterface|null $oDriver = null * * @return void */ diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/ChangePassword/ChangePasswordInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/Classes/Contact.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/Classes/Db.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/ContactsInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/DefaultContacts.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/DefaultContacts.php similarity index 95% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/DefaultContacts.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/DefaultContacts.php index f24c1fef49..a94b708efb 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Contacts/DefaultContacts.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Contacts/DefaultContacts.php @@ -1,600 +1,600 @@ -oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null; - $this->bUseDbPerUser = true; - } - - /** - * @param \RainLoop\Account $oAccount - * @staticvar array $aPdoCache - * @return \PDO - */ - private function getPDO($oAccount) - { - static $aPdoCache = array(); - - $sEmail = $oAccount->ParentEmailHelper(); - if (isset($aPdoCache[$sEmail])) - { - return $aPdoCache[$sEmail]; - } - - if (!\class_exists('PDO')) - { - throw new \Exception('class_exists=PDO'); - } - - $sVersionFile = ''; - $sDsn = ''; - - if ($this->bUseDbPerUser) - { - $sSubPath = APP_PRIVATE_DATA.'storage/contacts/'.\rtrim(\substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'; - if (!\is_dir($sSubPath)) - { - if (\mkdir($sSubPath, 0777, true) && \is_dir($sSubPath)) - { - $sVersionFile = $sSubPath.'.version'; - $sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite'; - } - } - else - { - $sVersionFile = $sSubPath.'.version'; - $sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite'; - } - } - else - { - $sVersionFile = APP_PRIVATE_DATA.'.version'; - $sDsn = 'sqlite:'.APP_PRIVATE_DATA.'contacts.sqlite'; - } - - $sDbLogin = ''; - $sDbPassword = ''; - - $oPdo = false; - try - { - $oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword); - if ($oPdo) - { - $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); - - if (!@\file_exists($sVersionFile) || - (string) @file_get_contents($sVersionFile) !== (string) \RainLoop\Providers\Contacts\Classes\Db::Version()) - { - $this->syncTables($oPdo, $sVersionFile); - } - - $oPdo->sqliteCreateFunction('SIMPLESEARCH', function ($sEmailValue, $sNameValue, $sMask) { - return \preg_match('/'.\preg_quote($sMask, '/').'/ui', - $sEmailValue.' '.$sNameValue) ? 1 : 0; - }); - - } - } - catch (\Exception $oException) - { - throw $oException; - $oPdo = false; - } - - if ($oPdo) - { - $aPdoCache[$oAccount->ParentEmailHelper()] = $oPdo; - } - - return $oPdo; - } - - protected function getWantedColumnsInfo($sTableName, $aCurrent) - { - $aColumns = array(); - foreach ($aCurrent as $sName => $sType) - { - $sSql = $sName.' '.$sType; - switch ($sType) - { - case 'INTEGER': - $sSql .= ' DEFAILT \'0\''; - break; - case 'TEXT': - $sSql .= ' DEFAILT \'\''; - break; - } - - $aColumns[$sName] = $sSql; - } - - if (0 === \count($aColumns)) - { - return ''; - } - - return 'CREATE TABLE '.$sTableName.' (' .\implode(', ', $aColumns).')'; - } - - /** - * @param \PDO $oAccount - * @param string $sTableName - */ - protected function getCurrentColumnsInfo($oPdo, $sTableName) - { - $oStmt = $this->prepareAndExecute($oPdo, 'SELECT `sql` FROM `sqlite_master` WHERE `tbl_name` = :TableName AND `type` = :Type', array( - ':TableName' => array($sTableName, \PDO::PARAM_STR), - ':Type' => array('table', \PDO::PARAM_STR) - )); - - if ($oStmt) - { - $mRow = $oStmt->fetch(\PDO::FETCH_ASSOC); - if ($mRow && isset($mRow['sql'])) - { - return (string) $mRow['sql']; - } - } - - return ''; - } - - /** - * @param \PDO $oPdo - * @param string $sVersionFile = '' - */ - private function syncTables($oPdo, $sVersionFile = '') - { - if ($this->oLogger) - { - $this->oLogger->Write('Start to sync', \MailSo\Log\Enumerations\Type::INFO); - } - - $aStrucure = \RainLoop\Providers\Contacts\Classes\Db::Strucure(); - foreach ($aStrucure as $sTableName => $aField) - { - $sCurrent = $this->getCurrentColumnsInfo($oPdo, $sTableName); - $sWanted = $this->getWantedColumnsInfo($sTableName, $aField); - - if (empty($sCurrent)) - { - $this->prepareAndExecute($oPdo, $sWanted); - } - else if ($sCurrent !== $sWanted) - { - $this->prepareAndExecute($oPdo, 'DROP TABLE IF EXISTS `'.$sTableName.'_old`'); - $this->prepareAndExecute($oPdo, 'ALTER TABLE `'.$sTableName.'` RENAME TO `'.$sTableName.'_old`'); - $this->prepareAndExecute($oPdo, $sWanted); - - $aNewKeys = array(); - $aOldKeys = array(); - foreach ($aField as $sKey => $sType) - { - $aNewKeys[] = $sKey; - $aOldKeys[] = false !== \strpos($sCurrent, $sKey.' ') ? $sKey : - (0 === \strpos($sType, 'INT') ? '\'0\'' : '\'\''); - } - - $sNewKeys = \implode(', ', $aNewKeys); - $sOldKeys = \implode(', ', $aOldKeys); - $this->prepareAndExecute($oPdo, 'INSERT INTO `'.$sTableName.'` ('.$sNewKeys.') SELECT '.$sOldKeys.' FROM `'.$sTableName.'_old`'); - - $this->prepareAndExecute($oPdo, 'DROP TABLE `'.$sTableName.'_old`'); - } - } - - @\file_put_contents($sVersionFile, \RainLoop\Providers\Contacts\Classes\Db::Version()); - - if ($this->oLogger) - { - $this->oLogger->Write('Stop to sync', \MailSo\Log\Enumerations\Type::INFO); - } - } - - /** - * @param \RainLoop\Account|\PDO $oAccountOrPdo - * @param string $sSql - * @param array $aParams - * - * @return \PDOStatement|null - */ - private function prepareAndExecute($oAccountOrPdo, $sSql, $aParams = array()) - { - if ($this->oLogger) - { - $this->oLogger->Write($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); - } - - $oPdo = $oAccountOrPdo instanceof \PDO ? $oAccountOrPdo : $this->getPDO($oAccountOrPdo); - $oStmt = $oPdo->prepare($sSql); - foreach ($aParams as $sName => $aValue) - { - $oStmt->bindValue($sName, $aValue[0], $aValue[1]); - } - -// $sLogSql = $sSql; -// foreach($aParams as $sName => $aValue) -// { -// $sLogSql = \str_replace($sName, $aValue[1] === \PDO::PARAM_INT ? $aValue[0] : '\''.$aValue[0].'\'', $sLogSql); -// } -// -// if ($this->oLogger) -// { -// $this->oLogger->Write($sLogSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); -// } - - $mResult = $oStmt->execute() ? $oStmt : null; - -// if ($this->oLogger) -// { -// $this->oLogger->Write('RESULT: '.($mResult ? 'true' : 'false'), \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); -// } - - return $mResult; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param bool $bSkipInsert = false - * - * @return int - */ - private function getUserId($oAccount, $bSkipInsert = false) - { - if (!$this->bUseDbPerUser) - { - $oStmt = $this->prepareAndExecute($oAccount, - 'SELECT IdUser FROM rlContactsUsers WHERE Email = :Email LIMIT 1', - array( - ':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR) - )); - - $mRow = $oStmt->fetch(\PDO::FETCH_ASSOC); - if ($mRow && isset($mRow['IdUser']) && \is_numeric($mRow['IdUser'])) - { - return (int) $mRow['IdUser']; - } - - if (!$bSkipInsert) - { - $oStmt->closeCursor(); - - $oStmt = $this->prepareAndExecute($oAccount, - 'INSERT INTO rlContactsUsers (Email) VALUES (:Email)', - array( - ':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR) - )); - - return $this->getUserId($oAccount, true); - } - - throw new \Exception('IdUser=0'); - } - - return 0; - } - - /** - * @param string $sSearch - * @return string - */ - private function convertSearchValue($sSearch) - { - return '%'.$sSearch.'%'; - } - - private function populateContactFromDB($iUserID, $aItem) - { - $oContact = null; - if (isset($aItem['IdContact'])) - { - $oContact = new \RainLoop\Providers\Contacts\Classes\Contact(); - $oContact->IdContact = (int) $aItem['IdContact']; - $oContact->IdUser = $iUserID; - $oContact->Type = (int) $aItem['Type']; - $oContact->Frec = (int) $aItem['Frec']; - $oContact->ListName = (string) $aItem['ListName']; - $oContact->Name = (string) $aItem['Name']; - $oContact->Emails = \explode(' ', \trim((string) $aItem['Emails'])); - $oContact->ImageHash = (string) $aItem['ImageHash']; - - $oContact->ParseData($aItem['Data']); - } - - return $oContact; - } - - /** - * @param \RainLoop\Account $oAccount - * @param int $iIdContact - * - * @return $oContact|null - */ - public function GetContactById($oAccount, $iIdContact) - { - $oResultContact = null; - - $iUserID = $this->getUserId($oAccount); - - $oStmt = $this->prepareAndExecute($oAccount, - 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'. - ' FROM rlContactsItems WHERE IdContact = :IdContact AND IdUser = :IdUser LIMIT 1', - array( - ':IdContact' => array($iIdContact, \PDO::PARAM_INT), - ':IdUser' => array($iUserID, \PDO::PARAM_INT) - )); - - $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); - if (\is_array($aFetch) && isset($aFetch[0]) && \is_array($aFetch[0])) - { - $oContact = $this->populateContactFromDB($iUserID, $aFetch[0]); - if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact) - { - $oResultContact = $oContact; - } - } - - return $oResultContact; - } - - /** - * @param \RainLoop\Account $oAccount - * @param int $iOffset = 0 - * @param int $iLimit = 20 - * @param string $sSearch = '' - * - * @return array - */ - public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '') - { - $iOffset = 0 <= $iOffset ? $iOffset : 0; - $iLimit = 0 < $iLimit ? (int) $iLimit : 0; - $sSearch = \trim($sSearch); - - $iUserID = $this->getUserId($oAccount); - - $sSql = 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'. - ' FROM rlContactsItems WHERE IdUser = :IdUser' - ; - - $aParams = array( - ':IdUser' => array($iUserID, \PDO::PARAM_INT), - ':limit' => array($iLimit, \PDO::PARAM_INT), - ':offset' => array($iOffset, \PDO::PARAM_INT) - ); - - if (0 < strlen($sSearch)) - { - if (\MailSo\Base\Utils::IsAscii($sSearch)) - { - $sSql .= ' AND Name LIKE :Search OR Emails LIKE :Search'; - $aParams[':Search'] = array($this->convertSearchValue($sSearch), \PDO::PARAM_STR); - } - else - { - $sSql .= ' AND SIMPLESEARCH(Emails, Name, :Search)'; - $aParams[':Search'] = array($sSearch, \PDO::PARAM_STR); - } - } - - $sSql .= ' ORDER BY ListName ASC LIMIT :limit OFFSET :offset'; - - $oStmt = $this->prepareAndExecute($oAccount, $sSql, $aParams); - - $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); - $aResult = array(); - if (\is_array($aFetch) && 0 < \count($aFetch)) - { - foreach ($aFetch as $aItem) - { - $oContact = $this->populateContactFromDB($iUserID, $aItem); - if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact) - { - $aResult[] = $oContact; - } - } - } - - unset($aFetch); - return $aResult; - } - - /** - * @param \RainLoop\Account $oAccount - * - * @return array - */ - public function GetContactsImageHashes($oAccount) - { - $iUserID = $this->getUserId($oAccount); - - $oStmt = $this->prepareAndExecute($oAccount, - 'SELECT Emails, ImageHash FROM rlContactsItems WHERE IdUser = :IdUser AND ImageHash <> :ImageHash', - array( - ':IdUser' => array($iUserID, \PDO::PARAM_INT), - ':ImageHash' => array('', \PDO::PARAM_STR) - )); - - $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); - $aResult = array(); - - if (\is_array($aFetch) && 0 < \count($aFetch)) - { - foreach ($aFetch as $aItem) - { - if (!empty($aItem['Emails']) && !empty($aItem['ImageHash'])) - { - $aEmails = \explode(' ', $aItem['Emails']); - foreach ($aEmails as $sEmail) - { - $sEmail = \trim($sEmail); - if (0 < strlen($sEmail)) - { - $aResult[$sEmail] = $aItem['ImageHash']; - } - } - } - } - } - - unset($aFetch); - return $aResult; - } - - /** - * @param \RainLoop\Account $oAccount - * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact - * - * @return bool - */ - public function CreateContact($oAccount, &$oContact) - { - $iUserID = $this->getUserId($oAccount); - - $oContact->IdUser = $iUserID; - - $oStmt = $this->prepareAndExecute($oAccount, - 'INSERT INTO rlContactsItems '. - '( IdUser, Type, Frec, ListName, Name, Emails, ImageHash, Data) VALUES '. - '(:IdUser, :Type, 0, :ListName, :Name, :Emails, :ImageHash, :Data)', - array( - ':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT), - ':Type' => array($oContact->Type, \PDO::PARAM_INT), - ':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR), - ':Name' => array($oContact->Name, \PDO::PARAM_STR), - ':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR), - ':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR), - ':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR), - )); - - if ($oStmt) - { - $iContactID = $this->getPDO($oAccount)->lastInsertId('IdContact'); - if (is_numeric($iContactID) && 0 < (int) $iContactID) - { - $oContact->IdContact = (int) $iContactID; - return true; - } - } - - throw new \Exception('CreateContact'); - } - - /** - * @param \RainLoop\Account $oAccount - * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact - * - * @return bool - */ - public function UpdateContact($oAccount, &$oContact) - { - $iUserID = $this->getUserId($oAccount); - - $oContact->IdUser = $iUserID; - - return !!$this->prepareAndExecute($oAccount, - 'UPDATE rlContactsItems SET'. - ' Type = :Type, ListName = :ListName, Name = :Name, Emails = :Emails,'. - ' ImageHash = :ImageHash, Data = :Data'. - ' WHERE IdContact = :IdContact AND IdUser = :IdUser', - array( - ':IdContact' => array($oContact->IdContact, \PDO::PARAM_INT), - ':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT), - ':Type' => array($oContact->Type, \PDO::PARAM_INT), - ':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR), - ':Name' => array($oContact->Name, \PDO::PARAM_STR), - ':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR), - ':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR), - ':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR), - )); - } - - /** - * @param \RainLoop\Account $oAccount - * @param array $aContactIds - * - * @return bool - */ - public function DeleteContacts($oAccount, $aContactIds) - { - $iUserID = $this->getUserId($oAccount); - - $aParams = array( - ':IdUser' => array($iUserID, \PDO::PARAM_INT), - ); - - $aInQuery = array(); - foreach ($aContactIds as $iIndex => $iId) - { - $aInQuery[] = ':IdContact_'.$iIndex; - $aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT); - } - - if (0 === \count($aInQuery)) - { - return false; - } - - return !!$this->prepareAndExecute($oAccount, - 'DELETE FROM rlContactsItems WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')', - $aParams); - } - - /** - * @return bool - */ - public function IsSupported() - { - $aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array(); - return \is_array($aDrivers) ? \in_array('sqlite', $aDrivers) : false; - } - - /** - * @param \RainLoop\Account $oAccount - * @param array $aContactIds - * - * @return bool - */ - public function IncFrec($oAccount, $aContactIds) - { - if (\is_array($aContactIds) && 0 < \count($aContactIds)) - { - $iUserID = $this->getUserId($oAccount); - - $aParams = array( - ':IdUser' => array($iUserID, \PDO::PARAM_INT), - ); - - $aInQuery = array(); - foreach ($aContactIds as $iIndex => $iId) - { - $aInQuery[] = ':IdContact_'.$iIndex; - $aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT); - } - - return !!$this->prepareAndExecute($oAccount, - 'UPDATE rlContactsItems SET Frec = Frec + 1 WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')', - $aParams); - } - - return false; - } +oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null; + $this->bUseDbPerUser = true; + } + + /** + * @param \RainLoop\Account $oAccount + * @staticvar array $aPdoCache + * @return \PDO + */ + private function getPDO($oAccount) + { + static $aPdoCache = array(); + + $sEmail = $oAccount->ParentEmailHelper(); + if (isset($aPdoCache[$sEmail])) + { + return $aPdoCache[$sEmail]; + } + + if (!\class_exists('PDO')) + { + throw new \Exception('class_exists=PDO'); + } + + $sVersionFile = ''; + $sDsn = ''; + + if ($this->bUseDbPerUser) + { + $sSubPath = APP_PRIVATE_DATA.'storage/contacts/'.\rtrim(\substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'; + if (!\is_dir($sSubPath)) + { + if (\mkdir($sSubPath, 0755, true) && \is_dir($sSubPath)) + { + $sVersionFile = $sSubPath.'.version'; + $sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite'; + } + } + else + { + $sVersionFile = $sSubPath.'.version'; + $sDsn = 'sqlite:'.$sSubPath.'contacts.sqlite'; + } + } + else + { + $sVersionFile = APP_PRIVATE_DATA.'.version'; + $sDsn = 'sqlite:'.APP_PRIVATE_DATA.'contacts.sqlite'; + } + + $sDbLogin = ''; + $sDbPassword = ''; + + $oPdo = false; + try + { + $oPdo = new \PDO($sDsn, $sDbLogin, $sDbPassword); + if ($oPdo) + { + $oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + + if (!@\file_exists($sVersionFile) || + (string) @file_get_contents($sVersionFile) !== (string) \RainLoop\Providers\Contacts\Classes\Db::Version()) + { + $this->syncTables($oPdo, $sVersionFile); + } + + $oPdo->sqliteCreateFunction('SIMPLESEARCH', function ($sEmailValue, $sNameValue, $sMask) { + return \preg_match('/'.\preg_quote($sMask, '/').'/ui', + $sEmailValue.' '.$sNameValue) ? 1 : 0; + }); + + } + } + catch (\Exception $oException) + { + throw $oException; + $oPdo = false; + } + + if ($oPdo) + { + $aPdoCache[$oAccount->ParentEmailHelper()] = $oPdo; + } + + return $oPdo; + } + + protected function getWantedColumnsInfo($sTableName, $aCurrent) + { + $aColumns = array(); + foreach ($aCurrent as $sName => $sType) + { + $sSql = $sName.' '.$sType; + switch ($sType) + { + case 'INTEGER': + $sSql .= ' DEFAILT \'0\''; + break; + case 'TEXT': + $sSql .= ' DEFAILT \'\''; + break; + } + + $aColumns[$sName] = $sSql; + } + + if (0 === \count($aColumns)) + { + return ''; + } + + return 'CREATE TABLE '.$sTableName.' (' .\implode(', ', $aColumns).')'; + } + + /** + * @param \PDO $oAccount + * @param string $sTableName + */ + protected function getCurrentColumnsInfo($oPdo, $sTableName) + { + $oStmt = $this->prepareAndExecute($oPdo, 'SELECT `sql` FROM `sqlite_master` WHERE `tbl_name` = :TableName AND `type` = :Type', array( + ':TableName' => array($sTableName, \PDO::PARAM_STR), + ':Type' => array('table', \PDO::PARAM_STR) + )); + + if ($oStmt) + { + $mRow = $oStmt->fetch(\PDO::FETCH_ASSOC); + if ($mRow && isset($mRow['sql'])) + { + return (string) $mRow['sql']; + } + } + + return ''; + } + + /** + * @param \PDO $oPdo + * @param string $sVersionFile = '' + */ + private function syncTables($oPdo, $sVersionFile = '') + { + if ($this->oLogger) + { + $this->oLogger->Write('Start to sync', \MailSo\Log\Enumerations\Type::INFO); + } + + $aStrucure = \RainLoop\Providers\Contacts\Classes\Db::Strucure(); + foreach ($aStrucure as $sTableName => $aField) + { + $sCurrent = $this->getCurrentColumnsInfo($oPdo, $sTableName); + $sWanted = $this->getWantedColumnsInfo($sTableName, $aField); + + if (empty($sCurrent)) + { + $this->prepareAndExecute($oPdo, $sWanted); + } + else if ($sCurrent !== $sWanted) + { + $this->prepareAndExecute($oPdo, 'DROP TABLE IF EXISTS `'.$sTableName.'_old`'); + $this->prepareAndExecute($oPdo, 'ALTER TABLE `'.$sTableName.'` RENAME TO `'.$sTableName.'_old`'); + $this->prepareAndExecute($oPdo, $sWanted); + + $aNewKeys = array(); + $aOldKeys = array(); + foreach ($aField as $sKey => $sType) + { + $aNewKeys[] = $sKey; + $aOldKeys[] = false !== \strpos($sCurrent, $sKey.' ') ? $sKey : + (0 === \strpos($sType, 'INT') ? '\'0\'' : '\'\''); + } + + $sNewKeys = \implode(', ', $aNewKeys); + $sOldKeys = \implode(', ', $aOldKeys); + $this->prepareAndExecute($oPdo, 'INSERT INTO `'.$sTableName.'` ('.$sNewKeys.') SELECT '.$sOldKeys.' FROM `'.$sTableName.'_old`'); + + $this->prepareAndExecute($oPdo, 'DROP TABLE `'.$sTableName.'_old`'); + } + } + + @\file_put_contents($sVersionFile, \RainLoop\Providers\Contacts\Classes\Db::Version()); + + if ($this->oLogger) + { + $this->oLogger->Write('Stop to sync', \MailSo\Log\Enumerations\Type::INFO); + } + } + + /** + * @param \RainLoop\Account|\PDO $oAccountOrPdo + * @param string $sSql + * @param array $aParams + * + * @return \PDOStatement|null + */ + private function prepareAndExecute($oAccountOrPdo, $sSql, $aParams = array()) + { + if ($this->oLogger) + { + $this->oLogger->Write($sSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); + } + + $oPdo = $oAccountOrPdo instanceof \PDO ? $oAccountOrPdo : $this->getPDO($oAccountOrPdo); + $oStmt = $oPdo->prepare($sSql); + foreach ($aParams as $sName => $aValue) + { + $oStmt->bindValue($sName, $aValue[0], $aValue[1]); + } + +// $sLogSql = $sSql; +// foreach($aParams as $sName => $aValue) +// { +// $sLogSql = \str_replace($sName, $aValue[1] === \PDO::PARAM_INT ? $aValue[0] : '\''.$aValue[0].'\'', $sLogSql); +// } +// +// if ($this->oLogger) +// { +// $this->oLogger->Write($sLogSql, \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); +// } + + $mResult = $oStmt->execute() ? $oStmt : null; + +// if ($this->oLogger) +// { +// $this->oLogger->Write('RESULT: '.($mResult ? 'true' : 'false'), \MailSo\Log\Enumerations\Type::INFO, 'SQLITE'); +// } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param bool $bSkipInsert = false + * + * @return int + */ + private function getUserId($oAccount, $bSkipInsert = false) + { + if (!$this->bUseDbPerUser) + { + $oStmt = $this->prepareAndExecute($oAccount, + 'SELECT IdUser FROM rlContactsUsers WHERE Email = :Email LIMIT 1', + array( + ':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR) + )); + + $mRow = $oStmt->fetch(\PDO::FETCH_ASSOC); + if ($mRow && isset($mRow['IdUser']) && \is_numeric($mRow['IdUser'])) + { + return (int) $mRow['IdUser']; + } + + if (!$bSkipInsert) + { + $oStmt->closeCursor(); + + $oStmt = $this->prepareAndExecute($oAccount, + 'INSERT INTO rlContactsUsers (Email) VALUES (:Email)', + array( + ':Email' => array($oAccount->ParentEmailHelper(), \PDO::PARAM_STR) + )); + + return $this->getUserId($oAccount, true); + } + + throw new \Exception('IdUser=0'); + } + + return 0; + } + + /** + * @param string $sSearch + * @return string + */ + private function convertSearchValue($sSearch) + { + return '%'.$sSearch.'%'; + } + + private function populateContactFromDB($iUserID, $aItem) + { + $oContact = null; + if (isset($aItem['IdContact'])) + { + $oContact = new \RainLoop\Providers\Contacts\Classes\Contact(); + $oContact->IdContact = (int) $aItem['IdContact']; + $oContact->IdUser = $iUserID; + $oContact->Type = (int) $aItem['Type']; + $oContact->Frec = (int) $aItem['Frec']; + $oContact->ListName = (string) $aItem['ListName']; + $oContact->Name = (string) $aItem['Name']; + $oContact->Emails = \explode(' ', \trim((string) $aItem['Emails'])); + $oContact->ImageHash = (string) $aItem['ImageHash']; + + $oContact->ParseData($aItem['Data']); + } + + return $oContact; + } + + /** + * @param \RainLoop\Account $oAccount + * @param int $iIdContact + * + * @return $oContact|null + */ + public function GetContactById($oAccount, $iIdContact) + { + $oResultContact = null; + + $iUserID = $this->getUserId($oAccount); + + $oStmt = $this->prepareAndExecute($oAccount, + 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'. + ' FROM rlContactsItems WHERE IdContact = :IdContact AND IdUser = :IdUser LIMIT 1', + array( + ':IdContact' => array($iIdContact, \PDO::PARAM_INT), + ':IdUser' => array($iUserID, \PDO::PARAM_INT) + )); + + $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); + if (\is_array($aFetch) && isset($aFetch[0]) && \is_array($aFetch[0])) + { + $oContact = $this->populateContactFromDB($iUserID, $aFetch[0]); + if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact) + { + $oResultContact = $oContact; + } + } + + return $oResultContact; + } + + /** + * @param \RainLoop\Account $oAccount + * @param int $iOffset = 0 + * @param int $iLimit = 20 + * @param string $sSearch = '' + * + * @return array + */ + public function GetContacts($oAccount, $iOffset = 0, $iLimit = 20, $sSearch = '') + { + $iOffset = 0 <= $iOffset ? $iOffset : 0; + $iLimit = 0 < $iLimit ? (int) $iLimit : 0; + $sSearch = \trim($sSearch); + + $iUserID = $this->getUserId($oAccount); + + $sSql = 'SELECT IdContact, Type, Frec, ListName, Name, Emails, ImageHash, Data'. + ' FROM rlContactsItems WHERE IdUser = :IdUser' + ; + + $aParams = array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ':limit' => array($iLimit, \PDO::PARAM_INT), + ':offset' => array($iOffset, \PDO::PARAM_INT) + ); + + if (0 < strlen($sSearch)) + { + if (\MailSo\Base\Utils::IsAscii($sSearch)) + { + $sSql .= ' AND Name LIKE :Search OR Emails LIKE :Search'; + $aParams[':Search'] = array($this->convertSearchValue($sSearch), \PDO::PARAM_STR); + } + else + { + $sSql .= ' AND SIMPLESEARCH(Emails, Name, :Search)'; + $aParams[':Search'] = array($sSearch, \PDO::PARAM_STR); + } + } + + $sSql .= ' ORDER BY ListName ASC LIMIT :limit OFFSET :offset'; + + $oStmt = $this->prepareAndExecute($oAccount, $sSql, $aParams); + + $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); + $aResult = array(); + if (\is_array($aFetch) && 0 < \count($aFetch)) + { + foreach ($aFetch as $aItem) + { + $oContact = $this->populateContactFromDB($iUserID, $aItem); + if ($oContact instanceof \RainLoop\Providers\Contacts\Classes\Contact) + { + $aResult[] = $oContact; + } + } + } + + unset($aFetch); + return $aResult; + } + + /** + * @param \RainLoop\Account $oAccount + * + * @return array + */ + public function GetContactsImageHashes($oAccount) + { + $iUserID = $this->getUserId($oAccount); + + $oStmt = $this->prepareAndExecute($oAccount, + 'SELECT Emails, ImageHash FROM rlContactsItems WHERE IdUser = :IdUser AND ImageHash <> :ImageHash', + array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ':ImageHash' => array('', \PDO::PARAM_STR) + )); + + $aFetch = $oStmt->fetchAll(\PDO::FETCH_ASSOC); + $aResult = array(); + + if (\is_array($aFetch) && 0 < \count($aFetch)) + { + foreach ($aFetch as $aItem) + { + if (!empty($aItem['Emails']) && !empty($aItem['ImageHash'])) + { + $aEmails = \explode(' ', $aItem['Emails']); + foreach ($aEmails as $sEmail) + { + $sEmail = \trim($sEmail); + if (0 < strlen($sEmail)) + { + $aResult[$sEmail] = $aItem['ImageHash']; + } + } + } + } + } + + unset($aFetch); + return $aResult; + } + + /** + * @param \RainLoop\Account $oAccount + * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact + * + * @return bool + */ + public function CreateContact($oAccount, &$oContact) + { + $iUserID = $this->getUserId($oAccount); + + $oContact->IdUser = $iUserID; + + $oStmt = $this->prepareAndExecute($oAccount, + 'INSERT INTO rlContactsItems '. + '( IdUser, Type, Frec, ListName, Name, Emails, ImageHash, Data) VALUES '. + '(:IdUser, :Type, 0, :ListName, :Name, :Emails, :ImageHash, :Data)', + array( + ':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT), + ':Type' => array($oContact->Type, \PDO::PARAM_INT), + ':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR), + ':Name' => array($oContact->Name, \PDO::PARAM_STR), + ':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR), + ':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR), + ':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR), + )); + + if ($oStmt) + { + $iContactID = $this->getPDO($oAccount)->lastInsertId('IdContact'); + if (is_numeric($iContactID) && 0 < (int) $iContactID) + { + $oContact->IdContact = (int) $iContactID; + return true; + } + } + + throw new \Exception('CreateContact'); + } + + /** + * @param \RainLoop\Account $oAccount + * @param \RainLoop\Providers\Contacts\Classes\Contact $oContact + * + * @return bool + */ + public function UpdateContact($oAccount, &$oContact) + { + $iUserID = $this->getUserId($oAccount); + + $oContact->IdUser = $iUserID; + + return !!$this->prepareAndExecute($oAccount, + 'UPDATE rlContactsItems SET'. + ' Type = :Type, ListName = :ListName, Name = :Name, Emails = :Emails,'. + ' ImageHash = :ImageHash, Data = :Data'. + ' WHERE IdContact = :IdContact AND IdUser = :IdUser', + array( + ':IdContact' => array($oContact->IdContact, \PDO::PARAM_INT), + ':IdUser' => array($oContact->IdUser, \PDO::PARAM_INT), + ':Type' => array($oContact->Type, \PDO::PARAM_INT), + ':ListName' => array($oContact->GenarateListName(), \PDO::PARAM_STR), + ':Name' => array($oContact->Name, \PDO::PARAM_STR), + ':Emails' => array($oContact->EmailsAsString(), \PDO::PARAM_STR), + ':ImageHash' => array($oContact->ImageHash, \PDO::PARAM_STR), + ':Data' => array($oContact->DataAsString(), \PDO::PARAM_STR), + )); + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aContactIds + * + * @return bool + */ + public function DeleteContacts($oAccount, $aContactIds) + { + $iUserID = $this->getUserId($oAccount); + + $aParams = array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ); + + $aInQuery = array(); + foreach ($aContactIds as $iIndex => $iId) + { + $aInQuery[] = ':IdContact_'.$iIndex; + $aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT); + } + + if (0 === \count($aInQuery)) + { + return false; + } + + return !!$this->prepareAndExecute($oAccount, + 'DELETE FROM rlContactsItems WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')', + $aParams); + } + + /** + * @return bool + */ + public function IsSupported() + { + $aDrivers = \class_exists('PDO') ? \PDO::getAvailableDrivers() : array(); + return \is_array($aDrivers) ? \in_array('sqlite', $aDrivers) : false; + } + + /** + * @param \RainLoop\Account $oAccount + * @param array $aContactIds + * + * @return bool + */ + public function IncFrec($oAccount, $aContactIds) + { + if (\is_array($aContactIds) && 0 < \count($aContactIds)) + { + $iUserID = $this->getUserId($oAccount); + + $aParams = array( + ':IdUser' => array($iUserID, \PDO::PARAM_INT), + ); + + $aInQuery = array(); + foreach ($aContactIds as $iIndex => $iId) + { + $aInQuery[] = ':IdContact_'.$iIndex; + $aParams[':IdContact_'.$iIndex] = array($iId, \PDO::PARAM_INT); + } + + return !!$this->prepareAndExecute($oAccount, + 'UPDATE rlContactsItems SET Frec = Frec + 1 WHERE IdUser = :IdUser AND IdContact IN ('.\implode(', ', $aInQuery).')', + $aParams); + } + + return false; + } } \ No newline at end of file diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DefaultDomain.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DomainAdminInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DomainInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DomainInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DomainInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DomainInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DomainSimpleInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DomainSimpleInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Domain/DomainSimpleInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Domain/DomainSimpleInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Login.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Login.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Login.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Login.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Login/DefaultLogin.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Login/DefaultLogin.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Login/DefaultLogin.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Login/DefaultLogin.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Login/LoginInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Login/LoginInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Login/LoginInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Login/LoginInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Settings.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Settings.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Settings.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Settings.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Settings/DefaultSettings.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Settings/SettingsInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php similarity index 95% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php index 13809961d5..641425e0c3 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/DefaultStorage.php @@ -1,290 +1,290 @@ -sDataPath = \rtrim(\trim($sStoragePath), '\\/'); - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * @param string $sValue - * - * @return bool - */ - public function Put($oAccount, $iStorageType, $sKey, $sValue) - { - return false !== @\file_put_contents( - $this->generateFileName($oAccount, $iStorageType, $sKey, true), $sValue); - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * @param resource $rSource - * - * @return bool - */ - public function PutFile($oAccount, $iStorageType, $sKey, $rSource) - { - $bResult = false; - if ($rSource) - { - $rOpenOutput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sKey, true), 'w+b'); - if ($rOpenOutput) - { - $bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rSource, array($rOpenOutput))); - @\fclose($rOpenOutput); - } - } - return $bResult; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * @param string $sSource - * - * @return bool - */ - public function MoveUploadedFile($oAccount, $iStorageType, $sKey, $sSource) - { - return @\move_uploaded_file($sSource, - $this->generateFileName($oAccount, $iStorageType, $sKey, true)); - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sSource - * @param string $sDest - * - * @return bool - */ - public function SaveFileToBase64File($oAccount, $iStorageType, $sSource, $sDest) - { - $bResult = false; - $rOpenInput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sSource), 'rb'); - $rOpenOutput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sDest, true), 'wb'); - - if ($rOpenInput && $rOpenOutput) - { - $aParam = array('line-length' => 76, 'line-break-chars' => "\r\n"); - $rFilter = @\stream_filter_append($rOpenOutput, 'convert.base64-encode', STREAM_FILTER_WRITE, $aParam); - if (@\is_resource($rFilter)) - { - $bResult = true; - } - } - - if ($bResult) - { - $bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rOpenInput, array($rOpenOutput))); - } - - if ($rOpenInput && $rOpenOutput) - { - @\fclose($rOpenInput); - @\fclose($rOpenOutput); - } - - return $bResult; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * @param mixed $mDefault = false - * - * @return mixed - */ - public function Get($oAccount, $iStorageType, $sKey, $mDefault = false) - { - $mValue = false; - $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); - if (\file_exists($sFileName)) - { - $mValue = \file_get_contents($sFileName); - } - - return false === $mValue ? $mDefault : $mValue; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * @param string $sOpenMode = 'rb' - * - * @return resource | bool - */ - public function GetFile($oAccount, $iStorageType, $sKey, $sOpenMode = 'rb') - { - $mResult = false; - $bCreate = !!\preg_match('/[wac]/', $sOpenMode); - - $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey, $bCreate); - if ($bCreate || \file_exists($sFileName)) - { - $mResult = @\fopen($sFileName, $sOpenMode); - } - - return $mResult; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * - * @return string | bool - */ - public function GetFileName($oAccount, $iStorageType, $sKey) - { - $mResult = false; - $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); - if (\file_exists($sFileName)) - { - $mResult = $sFileName; - } - - return $mResult; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * - * @return bool - */ - public function Clear($oAccount, $iStorageType, $sKey) - { - $mResult = true; - $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); - if (\file_exists($sFileName)) - { - $mResult = @\unlink($sFileName); - } - - return $mResult; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * - * @return int | bool - */ - public function FileSize($oAccount, $iStorageType, $sKey) - { - $mResult = false; - $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); - if (\file_exists($sFileName)) - { - $mResult = \filesize($sFileName); - } - - return $mResult; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iType - * @param string $sKey - * - * @return bool - */ - public function FileExists($oAccount, $iStorageType, $sKey) - { - return @\file_exists($this->generateFileName($oAccount, $iStorageType, $sKey)); - } - - /** - * @param int $iTimeToClearInHours = 24 - * - * @return bool - */ - public function GC($iTimeToClearInHours = 24) - { - if (0 < $iTimeToClearInHours) - { - \MailSo\Base\Utils::RecTimeDirRemove($this->sDataPath.'/tmp', 60 * 60 * $iTimeToClearInHours, \time()); - return true; - } - - return false; - } - - /** - * @param \RainLoop\Account|null $oAccount - * @param int $iStorageType - * @param string $sKey - * @param bool $bMkDir = false - * - * @return string - */ - private function generateFileName($oAccount, $iStorageType, $sKey, $bMkDir = false) - { - $sEmail = $oAccount ? \preg_replace('/[^a-z0-9\-\.@]+/', '_', - ('' === $oAccount->ParentEmail() ? '' : $oAccount->ParentEmail().'/').$oAccount->Email()) : ''; - - $sTypePath = $sKeyPath = ''; - switch ($iStorageType) - { - case \RainLoop\Providers\Storage\Enumerations\StorageType::TEMP: - $sTypePath = 'tmp'; - $sKeyPath = \md5($sKey); - $sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath; - break; - case \RainLoop\Providers\Storage\Enumerations\StorageType::USER: - case \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY: - $sTypePath = 'data'; - $sKeyPath = \md5($sKey); - $sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath; - break; - case \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG: - $sTypePath = 'cfg'; - $sKeyPath = \preg_replace('/[_]+/', '_', \preg_replace('/[^a-zA-Z0-9\/]/', '_', $sKey)); - break; - } - - if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY === $iStorageType) - { - $sFilePath = $this->sDataPath.'/'.$sTypePath.'/__nobody__/'.$sKeyPath; - } - else if (!empty($sEmail)) - { - $sFilePath = $this->sDataPath.'/'.$sTypePath.'/'.rtrim(substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'.$sKeyPath; - } - - if ($bMkDir && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath))) - { - if (!@\mkdir(\dirname($sFilePath), 0777, true)) - { - throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sFilePath.'"'); - } - } - - return $sFilePath; - } -} +sDataPath = \rtrim(\trim($sStoragePath), '\\/'); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sValue + * + * @return bool + */ + public function Put($oAccount, $iStorageType, $sKey, $sValue) + { + return false !== @\file_put_contents( + $this->generateFileName($oAccount, $iStorageType, $sKey, true), $sValue); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param resource $rSource + * + * @return bool + */ + public function PutFile($oAccount, $iStorageType, $sKey, $rSource) + { + $bResult = false; + if ($rSource) + { + $rOpenOutput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sKey, true), 'w+b'); + if ($rOpenOutput) + { + $bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rSource, array($rOpenOutput))); + @\fclose($rOpenOutput); + } + } + return $bResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sSource + * + * @return bool + */ + public function MoveUploadedFile($oAccount, $iStorageType, $sKey, $sSource) + { + return @\move_uploaded_file($sSource, + $this->generateFileName($oAccount, $iStorageType, $sKey, true)); + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sSource + * @param string $sDest + * + * @return bool + */ + public function SaveFileToBase64File($oAccount, $iStorageType, $sSource, $sDest) + { + $bResult = false; + $rOpenInput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sSource), 'rb'); + $rOpenOutput = @\fopen($this->generateFileName($oAccount, $iStorageType, $sDest, true), 'wb'); + + if ($rOpenInput && $rOpenOutput) + { + $aParam = array('line-length' => 76, 'line-break-chars' => "\r\n"); + $rFilter = @\stream_filter_append($rOpenOutput, 'convert.base64-encode', STREAM_FILTER_WRITE, $aParam); + if (@\is_resource($rFilter)) + { + $bResult = true; + } + } + + if ($bResult) + { + $bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rOpenInput, array($rOpenOutput))); + } + + if ($rOpenInput && $rOpenOutput) + { + @\fclose($rOpenInput); + @\fclose($rOpenOutput); + } + + return $bResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param mixed $mDefault = false + * + * @return mixed + */ + public function Get($oAccount, $iStorageType, $sKey, $mDefault = false) + { + $mValue = false; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mValue = \file_get_contents($sFileName); + } + + return false === $mValue ? $mDefault : $mValue; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param string $sOpenMode = 'rb' + * + * @return resource | bool + */ + public function GetFile($oAccount, $iStorageType, $sKey, $sOpenMode = 'rb') + { + $mResult = false; + $bCreate = !!\preg_match('/[wac]/', $sOpenMode); + + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey, $bCreate); + if ($bCreate || \file_exists($sFileName)) + { + $mResult = @\fopen($sFileName, $sOpenMode); + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return string | bool + */ + public function GetFileName($oAccount, $iStorageType, $sKey) + { + $mResult = false; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mResult = $sFileName; + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return bool + */ + public function Clear($oAccount, $iStorageType, $sKey) + { + $mResult = true; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mResult = @\unlink($sFileName); + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * + * @return int | bool + */ + public function FileSize($oAccount, $iStorageType, $sKey) + { + $mResult = false; + $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); + if (\file_exists($sFileName)) + { + $mResult = \filesize($sFileName); + } + + return $mResult; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iType + * @param string $sKey + * + * @return bool + */ + public function FileExists($oAccount, $iStorageType, $sKey) + { + return @\file_exists($this->generateFileName($oAccount, $iStorageType, $sKey)); + } + + /** + * @param int $iTimeToClearInHours = 24 + * + * @return bool + */ + public function GC($iTimeToClearInHours = 24) + { + if (0 < $iTimeToClearInHours) + { + \MailSo\Base\Utils::RecTimeDirRemove($this->sDataPath.'/tmp', 60 * 60 * $iTimeToClearInHours, \time()); + return true; + } + + return false; + } + + /** + * @param \RainLoop\Account|null $oAccount + * @param int $iStorageType + * @param string $sKey + * @param bool $bMkDir = false + * + * @return string + */ + private function generateFileName($oAccount, $iStorageType, $sKey, $bMkDir = false) + { + $sEmail = $oAccount ? \preg_replace('/[^a-z0-9\-\.@]+/', '_', + ('' === $oAccount->ParentEmail() ? '' : $oAccount->ParentEmail().'/').$oAccount->Email()) : ''; + + $sTypePath = $sKeyPath = ''; + switch ($iStorageType) + { + case \RainLoop\Providers\Storage\Enumerations\StorageType::TEMP: + $sTypePath = 'tmp'; + $sKeyPath = \md5($sKey); + $sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath; + break; + case \RainLoop\Providers\Storage\Enumerations\StorageType::USER: + case \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY: + $sTypePath = 'data'; + $sKeyPath = \md5($sKey); + $sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath; + break; + case \RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG: + $sTypePath = 'cfg'; + $sKeyPath = \preg_replace('/[_]+/', '_', \preg_replace('/[^a-zA-Z0-9\/]/', '_', $sKey)); + break; + } + + if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY === $iStorageType) + { + $sFilePath = $this->sDataPath.'/'.$sTypePath.'/__nobody__/'.$sKeyPath; + } + else if (!empty($sEmail)) + { + $sFilePath = $this->sDataPath.'/'.$sTypePath.'/'.rtrim(substr($sEmail, 0, 2), '@').'/'.$sEmail.'/'.$sKeyPath; + } + + if ($bMkDir && !empty($sFilePath) && !@\is_dir(\dirname($sFilePath))) + { + if (!@\mkdir(\dirname($sFilePath), 0755, true)) + { + throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sFilePath.'"'); + } + } + + return $sFilePath; + } +} diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/Enumerations/StorageType.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadClientError.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadClientError.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadClientError.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadClientError.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadError.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadError.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadError.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/Enumerations/UploadError.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/StorageInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/StorageInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Storage/StorageInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Storage/StorageInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Suggestions.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Suggestions.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Suggestions.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Suggestions.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Providers/Suggestions/SuggestionsInterface.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Service.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Service.php similarity index 99% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Service.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Service.php index 66b3727353..2f8d78c87d 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Service.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Service.php @@ -174,6 +174,7 @@ public function Handle() $sResult .= ' [version:'.APP_VERSION; $sResult .= '][time:'.substr(\microtime(true) - APP_START, 0, 6); $sResult .= '][cached:'.($bCached ? 'true' : 'false'); + $sResult .= '][session:'.md5(\RainLoop\Utils::GetShortToken()); $sResult .= '] -->'; } diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/ServiceActions.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/ServiceActions.php similarity index 94% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/ServiceActions.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/ServiceActions.php index 2d5cba6f17..e6bb4b9535 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/ServiceActions.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/ServiceActions.php @@ -1,951 +1,943 @@ -oHttp = $oHttp; - $this->oActions = $oActions; - $this->aPaths = array(); - } - - /** - * @return \MailSo\Log\Logger - */ - public function Logger() - { - return $this->oActions->Logger(); - } - - /** - * @return \RainLoop\Plugins\Manager - */ - public function Plugins() - { - return $this->oActions->Plugins(); - } - - /** - * @return \RainLoop\Application - */ - public function Config() - { - return $this->oActions->Config(); - } - - /** - * @return \MailSo\Cache\CacheClient - */ - public function Cacher() - { - return $this->oActions->Cacher(); - } - - /** - * @return \RainLoop\Providers\Storage - */ - public function StorageProvider() - { - return $this->oActions->StorageProvider(); - } - - /** - * @param array $aPaths - * - * @return \RainLoop\ServiceActions - */ - public function SetPaths($aPaths) - { - $this->aPaths = \is_array($aPaths) ? $aPaths : array(); - return $this; - } - - /** - * @param string $sQuery - * - * @return \RainLoop\ServiceActions - */ - public function SetQuery($sQuery) - { - $this->sQuery = $sQuery; - return $this; - } - - /** - * @return string - */ - public function ServiceAjax() - { - @\ob_start(); - - $aResponseItem = null; - $oException = null; - - $sAction = $this->oHttp->GetPost('Action', null); - if (empty($sAction) && $this->oHttp->IsGet() && !empty($this->aPaths[2])) - { - $sAction = $this->aPaths[2]; - } - - try - { - if ($this->oHttp->IsPost() && - $this->Config()->Get('security', 'csrf_protection', false) - && $this->oHttp->GetPost('XToken', '') !== \RainLoop\Utils::GetCsrfToken()) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidToken); - } - else if (!empty($sAction)) - { - $sMethodName = 'Do'.$sAction; - - $this->Logger()->Write('Action: '.$sMethodName, \MailSo\Log\Enumerations\Type::NOTE, 'AJAX'); - - $aPost = $this->oHttp->GetPostAsArray(); - if (\is_array($aPost) && 0 < \count($aPost)) - { - $this->oActions->SetActionParams($aPost, $sMethodName); - switch ($sMethodName) - { - case 'DoLogin': - case 'DoAdminLogin': - case 'DoAccountAdd': - $this->Logger()->AddSecret($this->oActions->GetActionParam('Password', '')); - break; - case 'DoChangePassword': - $this->Logger()->AddSecret($this->oActions->GetActionParam('PrevPassword', '')); - $this->Logger()->AddSecret($this->oActions->GetActionParam('NewPassword', '')); - break; - } - - $this->Logger()->Write(\MailSo\Base\Utils::Php2js($aPost), \MailSo\Log\Enumerations\Type::INFO, 'POST', true); - } - else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) - { - $this->oActions->SetActionParams(array( - 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] - ), $sMethodName); - } - - if (\method_exists($this->oActions, $sMethodName) && - \is_callable(array($this->oActions, $sMethodName))) - { - $this->Plugins()->RunHook('ajax.action-pre-call', array($sAction)); - $aResponseItem = \call_user_func(array($this->oActions, $sMethodName)); - $this->Plugins()->RunHook('ajax.action-post-call', array($sAction, &$aResponseItem)); - } - else if ($this->Plugins()->HasAdditionalAjax($sMethodName)) - { - $this->Plugins()->RunHook('ajax.action-pre-call', array($sAction)); - $aResponseItem = $this->Plugins()->RunAdditionalAjax($sMethodName); - $this->Plugins()->RunHook('ajax.action-post-call', array($sAction, &$aResponseItem)); - } - } - - if (!\is_array($aResponseItem)) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); - } - } - catch (\Exception $oException) - { - $oException = /* @var $oException \Exception */ $oException; - - $bLogout = ('Folders' === $sAction && $oException instanceof \RainLoop\Exceptions\ClientException); - if ($bLogout) - { - $this->oActions->ClearAuthToken(); - } - - $aResponseItem = $this->oActions->ExceptionResponse( - empty($sAction) ? 'Unknown' : $sAction, $oException); - - if ($bLogout && \is_array($aResponseItem)) - { - $aResponseItem['Logout'] = true; - } - } - - if (\is_array($aResponseItem)) - { - $aResponseItem['Time'] = (int) ((\microtime(true) - APP_START) * 1000); - } - - $this->Plugins()->RunHook('filter.ajax-response', array($sAction, &$aResponseItem)); - - @\header('Content-Type: application/json; charset=utf-8'); - $sResult = \MailSo\Base\Utils::Php2js($aResponseItem); - - $sObResult = @\ob_get_clean(); - - if ($this->Logger()->IsEnabled()) - { - if (0 < \strlen($sObResult)) - { - $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); - } - - if ($oException) - { - $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); - } - - $iLimit = (int) $this->Config()->Get('labs', 'log_ajax_response_write_limit', 0); - $this->Logger()->Write(0 < $iLimit && $iLimit < \strlen($sResult) - ? \substr($sResult, 0, $iLimit).'...' : $sResult, \MailSo\Log\Enumerations\Type::INFO, 'AJAX'); - } - - return $sResult; - } - - /** - * @return string - */ - public function ServiceAppend() - { - @\ob_start(); - $bResponse = false; - $oException = null; - try - { - if (\method_exists($this->oActions, 'Append') && - \is_callable(array($this->oActions, 'Append'))) - { - $this->oActions->SetActionParams($this->oHttp->GetPostAsArray(), 'Append'); - $bResponse = \call_user_func(array($this->oActions, 'Append')); - } - } - catch (\Exception $oException) - { - $bResponse = false; - } - - @\header('Content-Type: text/plain; charset=utf-8'); - $sResult = true === $bResponse ? '1' : '0'; - - $sObResult = @\ob_get_clean(); - if (0 < \strlen($sObResult)) - { - $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); - } - - if ($oException) - { - $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); - } - - $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPEND'); - - return $sResult; - } - - /** - * @param string $sAction - * - * @return string - */ - private function privateUpload($sAction) - { - @\ob_start(); - $aResponseItem = null; - try - { - if (\method_exists($this->oActions, $sAction) && - \is_callable(array($this->oActions, $sAction))) - { - $this->oActions->SetActionParams($this->oHttp->GetQueryAsArray(), $sAction); - - $aResponseItem = \call_user_func(array($this->oActions, $sAction)); - } - - if (!is_array($aResponseItem)) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); - } - } - catch (\Exception $oException) - { - $aResponseItem = $this->oActions->ExceptionResponse($sAction, $oException); - } - - if ('iframe' === $this->oHttp->GetPost('jua-post-type', '')) - { - @\header('Content-Type: text/html; charset=utf-8'); - } - else - { - @\header('Content-Type: application/json; charset=utf-8'); - } - - $this->Plugins()->RunHook('filter.upload-response', array(&$aResponseItem)); - $sResult = \MailSo\Base\Utils::Php2js($aResponseItem); - - $sObResult = @\ob_get_clean(); - if (0 < \strlen($sObResult)) - { - $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); - } - - $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'UPLOAD'); - - return $sResult; - } - - /** - * @return string - */ - public function ServiceUpload() - { - return $this->privateUpload('Upload'); - } - - /** - * @return string - */ - public function ServiceUploadBackground() - { - return $this->privateUpload('UploadBackground'); - } - - /** - * @return string - */ - public function ServiceRaw() - { - $sResult = ''; - $sRawError = ''; - $sAction = empty($this->aPaths[2]) ? '' : $this->aPaths[2]; - $oException = null; - - try - { - $sRawError = 'Invalid action'; - if (0 !== \strlen($sAction)) - { - $sMethodName = 'Raw'.$sAction; - if (\method_exists($this->oActions, $sMethodName)) - { - $sRawError = ''; - $this->oActions->SetActionParams(array( - 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] - ), $sMethodName); - - if (!\call_user_func(array($this->oActions, $sMethodName))) - { - $sRawError = 'False result'; - } - else - { - $sRawError = ''; - } - } - } - } - catch (\RainLoop\Exceptions\ClientException $oException) - { - $sRawError = 'Exception as result'; - switch ($oException->getCode()) - { - case \RainLoop\Notifications::AuthError: - $sRawError = 'Authentication failed'; - break; - } - } - catch (\Exception $oException) - { - $sRawError = 'Exception as result'; - } - - if (0 < \strlen($sRawError)) - { - $this->oActions->Logger()->Write($sRawError, \MailSo\Log\Enumerations\Type::ERROR); - } - - if ($oException) - { - $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR, 'RAW'); - } - - return $sResult; - } - - /** - * @return string - */ - public function ServiceLang() - { - $sResult = ''; - @\header('Content-Type: application/javascript; charset=utf-8'); - - if (!empty($this->aPaths[2])) - { - $sLanguage = $this->oActions->ValidateLanguage($this->aPaths[2]); - - $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); - if (!empty($sLanguage) && $bCacheEnabled) - { - $this->oActions->verifyCacheByKey($this->sQuery); - } - - $sCacheFileName = ''; - if ($bCacheEnabled) - { - $sCacheFileName = 'LANG:'.$this->oActions->Plugins()->Hash().$sLanguage.APP_VERSION; - $sResult = $this->Cacher()->Get($sCacheFileName); - } - - if (0 === \strlen($sResult)) - { - $sResult = $this->compileLanguage($sLanguage, false); - if ($bCacheEnabled && 0 < \strlen($sCacheFileName)) - { - $this->Cacher()->Set($sCacheFileName, $sResult); - } - } - - if ($bCacheEnabled) - { - $this->oActions->cacheByKey($this->sQuery); - } - } - - return $sResult; - } - - /** - * @return string - */ - public function ServiceTemplates() - { - $sResult = ''; - @\header('Content-Type: application/javascript; charset=utf-8'); - - $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); - if ($bCacheEnabled) - { - $this->oActions->verifyCacheByKey($this->sQuery); - } - - $sCacheFileName = ''; - if ($bCacheEnabled) - { - $sCacheFileName = 'TEMPLATES:'.$this->oActions->Plugins()->Hash().APP_VERSION; - $sResult = $this->Cacher()->Get($sCacheFileName); - } - - if (0 === \strlen($sResult)) - { - $sResult = $this->compileTemplates(false); - if ($bCacheEnabled && 0 < \strlen($sCacheFileName)) - { - $this->Cacher()->Set($sCacheFileName, $sResult); - } - } - - if ($bCacheEnabled) - { - $this->oActions->cacheByKey($this->sQuery); - } - - return $sResult; - } - - /** - * @return string - */ - public function ServicePlugins() - { - $sResult = ''; - $bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2]; - - @\header('Content-Type: application/javascript; charset=utf-8'); - - $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); - if ($bCacheEnabled) - { - $this->oActions->verifyCacheByKey($this->sQuery); - } - - $sCacheFileName = ''; - if ($bCacheEnabled) - { - $sCacheFileName = 'PLUGIN:'.$this->oActions->Plugins()->Hash().APP_VERSION; - $sResult = $this->Cacher()->Get($sCacheFileName); - } - - if (0 === strlen($sResult)) - { - $sResult = $this->Plugins()->CompileJs($bAdmin); - if ($bCacheEnabled && 0 < \strlen($sCacheFileName)) - { - $this->Cacher()->Set($sCacheFileName, $sResult); - } - } - - if ($bCacheEnabled) - { - $this->oActions->cacheByKey($this->sQuery); - } - - return $sResult; - } - - /** - * @return string - */ - public function ServiceCss() - { - $sResult = ''; - $bCustom = false; - $oAccount = null; - $oSettings = null; - - $bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2]; - $bJson = !empty($this->aPaths[7]) && 'Json' === $this->aPaths[7]; - - if ($bJson) - { - @\header('Content-Type: application/json; charset=utf-8'); - } - else - { - @\header('Content-Type: text/css; charset=utf-8'); - } - - $sTheme = ''; - if (!empty($this->aPaths[4])) - { - $sTheme = $this->oActions->ValidateTheme($this->aPaths[4]); - if ('Custom' === $sTheme && !empty($this->aPaths[1]) && '0' !== $this->aPaths[1]) - { - $bCustom = true; - $oAccount = $this->oActions->GetAccount(false); - if ($oAccount) - { - $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); - } - } - - $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); - if ($bCacheEnabled && !$bCustom) - { - $this->oActions->verifyCacheByKey($this->sQuery); - } - - $sCacheFileName = ''; - if ($bCacheEnabled && !$bCustom) - { - $sCacheFileName = 'THEMES/PLUGINS:'.$sTheme.':'.$this->Plugins()->Hash(); - $sResult = $this->Cacher()->Get($sCacheFileName); - } - - if (0 === \strlen($sResult)) - { - try - { - include_once APP_VERSION_ROOT_PATH.'app/libraries/lessphp/ctype.php'; - include_once APP_VERSION_ROOT_PATH.'app/libraries/lessphp/lessc.inc.php'; - - $oLess = new \lessc(); - $oLess->setFormatter('compressed'); - - $aResult = array(); - - $sThemeValuesFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/values.less'; - if ($bCustom) - { - $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-light.less'; - if ($oSettings) - { - if (\RainLoop\Enumerations\CustomThemeType::LIGHT === (string) $oSettings->GetConf('CustomThemeType', \RainLoop\Enumerations\CustomThemeType::LIGHT)) - { - $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-light.less'; - } - else - { - $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-dark.less'; - } - } - } - else - { - $sThemeFile = APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/styles.less'; - } - - $sThemeTemplateFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/template.less'; - - if (\file_exists($sThemeFile) && \file_exists($sThemeTemplateFile) && \file_exists($sThemeValuesFile)) - { - $aResult[] = '@base: "'.APP_WEB_PATH.'themes/'.$sTheme.'/";'; - $aResult[] = \file_get_contents($sThemeValuesFile); - $aResult[] = \file_get_contents($sThemeFile); - $aResult[] = \file_get_contents($sThemeTemplateFile); - - if (\file_exists(APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/ext.less')) - { - $aResult[] = \file_get_contents(APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/ext.less'); - } - } - - $aResult[] = $this->Plugins()->CompileCss($bAdmin); - - $sResult = $oLess->compile(\implode("\n", $aResult)); - - if ($bCustom && $oAccount) - { - $mData = $this->oActions->StorageProvider()->Get($oAccount, StorageType::USER, 'CustomThemeBackground', ''); - if (!empty($mData) && 'data:' === \substr($mData, 0, 5)) - { - $sResult = \str_replace('background-image:link', 'background-image:url("'.$mData.'")', $sResult); - } - } - - if ($bCacheEnabled && !$bCustom) - { - if (0 < \strlen($sCacheFileName)) - { - $this->Cacher()->Set($sCacheFileName, $sResult); - } - } - } - catch (\Exception $oException) - { - $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR, 'LESS'); - } - } - - if ($bCacheEnabled && !$bCustom) - { - $this->oActions->cacheByKey($this->sQuery); - } - } - - return $bJson ? \MailSo\Base\Utils::Php2js(array($sTheme, $sResult)) : $sResult; - } - - /** - * @return string - */ - public function ServiceSocialGoogle() - { - return $this->oActions->Social()->GooglePopupService(); - } - - /** - * @return string - */ - public function ServiceSocialFacebook() - { - return $this->oActions->Social()->FacebookPopupService(); - } - - /** - * @return string - */ - public function ServiceSocialTwitter() - { - return $this->oActions->Social()->TwitterPopupService(); - } - - /** - * @return string - */ - public function ServiceAppData() - { - return $this->localAppData(false); - } - - /** - * @return string - */ - public function ServiceAdminAppData() - { - return $this->localAppData(true); - } - - /** - * @return string - */ - public function ServiceNoScript() - { - return $this->localError($this->oActions->StaticI18N('STATIC/NO_SCRIPT_TITLE'), $this->oActions->StaticI18N('STATIC/NO_SCRIPT_DESC')); - } - - /** - * @return string - */ - public function ServiceNoCookie() - { - return $this->localError($this->oActions->StaticI18N('STATIC/NO_COOKIE_TITLE'), $this->oActions->StaticI18N('STATIC/NO_COOKIE_DESC')); - } - - /** - * @return string - */ - public function ServiceBadBrowser() - { - $sTitle = $this->oActions->StaticI18N('STATIC/BAD_BROWSER_TITLE'); - $sDesc = \nl2br($this->oActions->StaticI18N('STATIC/BAD_BROWSER_DESC')); - - @\header('Content-Type: text/html; charset=utf-8'); - return \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/BadBrowser.html'), array( - '{{BaseWebStaticPath}}' => APP_WEB_STATIC_PATH, - '{{ErrorTitle}}' => $sTitle, - '{{ErrorHeader}}' => $sTitle, - '{{ErrorDesc}}' => $sDesc - )); - } - - /** - * @return string - */ - public function ServicePing() - { - @\header('Content-Type: text/plain; charset=utf-8'); - $this->oActions->Logger()->Write('Pong', \MailSo\Log\Enumerations\Type::INFO, 'PING'); - return 'Pong'; - } - - /** - * @return string - */ - public function ServiceInfo() - { - if ($this->oActions->IsAdminLoggined(false)) - { - @\header('Content-Type: text/html; charset=utf-8'); - \phpinfo(); - } - } - - /** - * @return string - */ - public function ServiceExternalLogin() - { - if ($this->oActions->Config()->Get('labs', 'allow_external_login', false)) - { - $oException = null; - try - { - $sEmail = trim($this->oHttp->GetRequest('Email', '')); - $sLogin = trim($this->oHttp->GetRequest('Login', '')); - $sPassword = $this->oHttp->GetRequest('Password', ''); - - $this->oActions->Logger()->AddSecret($sPassword); - - if (0 === \strlen($sLogin)) - { - $sLogin = $sEmail; - } - - $oAccount = $this->oActions->LoginProcess($sEmail, $sLogin, $sPassword); - $this->oActions->AuthProcess($oAccount); - } - catch (\Exception $oException) - { - $this->oActions->Logger()->WriteException($oException); - } - } - - $this->oActions->Location('./'); - return ''; - } - - /** - * @return string - */ - public function ServiceChange() - { - if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) - { - $oAccountToLogin = null; - $sEmail = empty($this->aPaths[2]) ? '' : \strtolower(\urldecode(\trim($this->aPaths[2]))); - if (!empty($sEmail)) - { - $oAccount = $this->oActions->GetAccount(); - if ($oAccount) - { - $aAccounts = $this->oActions->GetAccounts($oAccount); - if (isset($aAccounts[$sEmail])) - { - $oAccountToLogin = $this->oActions->GetAccountFromCustomToken($aAccounts[$sEmail], false); - } - } - } - - if ($oAccountToLogin) - { - $this->oActions->AuthProcess($oAccountToLogin, true); - } - } - - $this->oActions->Location('./'); - return ''; - } - - /** - * @param string $sTitle - * @param string $sDesc - * - * @return string - */ - private function localError($sTitle, $sDesc) - { - @header('Content-Type: text/html; charset=utf-8'); - return $this->oActions->ErrorTemplates($sTitle, \nl2br($sDesc)); - } - - /** - * @param bool $bAdmin = true - * - * @return string - */ - private function localAppData($bAdmin = false) - { - @\header('Content-Type: application/javascript; charset=utf-8'); - @\header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); - @\header('Last-Modified: '.\gmdate('D, d M Y H:i:s').' GMT'); - @\header('Cache-Control: no-store, no-cache, must-revalidate'); - @\header('Cache-Control: post-check=0, pre-check=0', false); - @\header('Pragma: no-cache'); - - $sAuthAccountHash = ''; - if (!$bAdmin) - { - $sAuthAccountHash = $this->oActions->GetSpecAuthTokenWithDeletion(); - if (empty($sAuthAccountHash)) - { - $sAuthAccountHash = $this->oActions->GetSpecAuthToken(); - } - - if (empty($sAuthAccountHash)) - { - $sSignMeToken = \RainLoop\Utils::GetCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY, ''); - if (!empty($sSignMeToken)) - { - $oAccount = $this->oActions->GetAccountFromCustomToken($this->StorageProvider()->Get(null, - \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, - 'SignMe/UserToken/'.$sSignMeToken - ), false); - - if ($oAccount) - { - $this->oActions->AuthProcess($oAccount); - $sAuthAccountHash = $this->oActions->GetSpecAuthToken(); - } - } - } - - $this->oActions->SetSpecAuthToken($sAuthAccountHash); - } - - $sResult = $this->compileAppData($this->oActions->AppData($bAdmin, $sAuthAccountHash), false); - - $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPDATA'); - - return $sResult; - } - - /** - * @param bool $bAdmin = false - * @param bool $bWrapByScriptTag = true - * - * @return string - */ - private function compileTemplates($bAdmin = false, $bWrapByScriptTag = false) - { - $sHtml = \RainLoop\Utils::CompileTemplates(APP_VERSION_ROOT_PATH.'app/templates/Views', $this->oActions). - $this->oActions->Plugins()->CompileTemplate($bAdmin); - - return - ($bWrapByScriptTag ? '' : '') - ; - } - - /** - * @param string $sLanguage - * @param bool $bWrapByScriptTag = true - * - * @return string - */ - private function compileLanguage($sLanguage, $bWrapByScriptTag = true) - { - $aResultLang = array(); - - $sMoment = 'window.moment && window.moment.lang && window.moment.lang(\'en\');'; - $sMomentFileName = APP_VERSION_ROOT_PATH.'app/i18n/moment/'.$sLanguage.'.js'; - if (\file_exists($sMomentFileName)) - { - $sMoment = \file_get_contents($sMomentFileName); - $sMoment = \preg_replace('/\/\/[^\n]+\n/', '', $sMoment); - } - - \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'app/i18n/langs.ini', $aResultLang); - \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'langs/'.$sLanguage.'.ini', $aResultLang); - - $this->Plugins()->ReadLang($sLanguage, $aResultLang); - - $sLangJs = ''; - $aLangKeys = \array_keys($aResultLang); - foreach ($aLangKeys as $sKey) - { - $sString = isset($aResultLang[$sKey]) ? $aResultLang[$sKey] : $sKey; - - $sLangJs .= '"'.\str_replace('"', '\\"', \str_replace('\\', '\\\\', $sKey)).'":' - .'"'.\str_replace(array("\r", "\n", "\t"), array('\r', '\n', '\t'), - \str_replace('"', '\\"', \str_replace('\\', '\\\\', $sString))).'",'; - } - - $sResult = empty($sLangJs) ? 'null' : '{'.\substr($sLangJs, 0, -1).'}'; - - return - ($bWrapByScriptTag ? '' : '') - ; - } - - /** - * @param array $aAppData - * @param bool $bWrapByScriptTag = true - * - * @return string - */ - private function compileAppData($aAppData, $bWrapByScriptTag = true) - { - return - ($bWrapByScriptTag ? '' : '') - ; - } -} +oHttp = $oHttp; + $this->oActions = $oActions; + $this->aPaths = array(); + } + + /** + * @return \MailSo\Log\Logger + */ + public function Logger() + { + return $this->oActions->Logger(); + } + + /** + * @return \RainLoop\Plugins\Manager + */ + public function Plugins() + { + return $this->oActions->Plugins(); + } + + /** + * @return \RainLoop\Application + */ + public function Config() + { + return $this->oActions->Config(); + } + + /** + * @return \MailSo\Cache\CacheClient + */ + public function Cacher() + { + return $this->oActions->Cacher(); + } + + /** + * @return \RainLoop\Providers\Storage + */ + public function StorageProvider() + { + return $this->oActions->StorageProvider(); + } + + /** + * @param array $aPaths + * + * @return \RainLoop\ServiceActions + */ + public function SetPaths($aPaths) + { + $this->aPaths = \is_array($aPaths) ? $aPaths : array(); + return $this; + } + + /** + * @param string $sQuery + * + * @return \RainLoop\ServiceActions + */ + public function SetQuery($sQuery) + { + $this->sQuery = $sQuery; + return $this; + } + + /** + * @return string + */ + public function ServiceAjax() + { + @\ob_start(); + + $aResponseItem = null; + $oException = null; + + $sAction = $this->oHttp->GetPost('Action', null); + if (empty($sAction) && $this->oHttp->IsGet() && !empty($this->aPaths[2])) + { + $sAction = $this->aPaths[2]; + } + + try + { + if ($this->oHttp->IsPost() && + $this->Config()->Get('security', 'csrf_protection', false) + && $this->oHttp->GetPost('XToken', '') !== \RainLoop\Utils::GetCsrfToken()) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidToken); + } + else if (!empty($sAction)) + { + $sMethodName = 'Do'.$sAction; + + $this->Logger()->Write('Action: '.$sMethodName, \MailSo\Log\Enumerations\Type::NOTE, 'AJAX'); + + $aPost = $this->oHttp->GetPostAsArray(); + if (\is_array($aPost) && 0 < \count($aPost)) + { + $this->oActions->SetActionParams($aPost, $sMethodName); + switch ($sMethodName) + { + case 'DoLogin': + case 'DoAdminLogin': + case 'DoAccountAdd': + $this->Logger()->AddSecret($this->oActions->GetActionParam('Password', '')); + break; + case 'DoChangePassword': + $this->Logger()->AddSecret($this->oActions->GetActionParam('PrevPassword', '')); + $this->Logger()->AddSecret($this->oActions->GetActionParam('NewPassword', '')); + break; + } + + $this->Logger()->Write(\MailSo\Base\Utils::Php2js($aPost), \MailSo\Log\Enumerations\Type::INFO, 'POST', true); + } + else if (3 < \count($this->aPaths) && $this->oHttp->IsGet()) + { + $this->oActions->SetActionParams(array( + 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] + ), $sMethodName); + } + + if (\method_exists($this->oActions, $sMethodName) && + \is_callable(array($this->oActions, $sMethodName))) + { + $this->Plugins()->RunHook('ajax.action-pre-call', array($sAction)); + $aResponseItem = \call_user_func(array($this->oActions, $sMethodName)); + $this->Plugins()->RunHook('ajax.action-post-call', array($sAction, &$aResponseItem)); + } + else if ($this->Plugins()->HasAdditionalAjax($sMethodName)) + { + $this->Plugins()->RunHook('ajax.action-pre-call', array($sAction)); + $aResponseItem = $this->Plugins()->RunAdditionalAjax($sMethodName); + $this->Plugins()->RunHook('ajax.action-post-call', array($sAction, &$aResponseItem)); + } + } + + if (!\is_array($aResponseItem)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); + } + } + catch (\Exception $oException) + { + $aResponseItem = $this->oActions->ExceptionResponse( + empty($sAction) ? 'Unknown' : $sAction, $oException); + + if (\is_array($aResponseItem) && 'Folders' === $sAction && $oException instanceof \RainLoop\Exceptions\ClientException) + { + $aResponseItem['Logout'] = true; + } + } + + if (\is_array($aResponseItem)) + { + $aResponseItem['Time'] = (int) ((\microtime(true) - APP_START) * 1000); + } + + $this->Plugins()->RunHook('filter.ajax-response', array($sAction, &$aResponseItem)); + + @\header('Content-Type: application/json; charset=utf-8'); + $sResult = \MailSo\Base\Utils::Php2js($aResponseItem); + + $sObResult = @\ob_get_clean(); + + if ($this->Logger()->IsEnabled()) + { + if (0 < \strlen($sObResult)) + { + $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); + } + + if ($oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + $iLimit = (int) $this->Config()->Get('labs', 'log_ajax_response_write_limit', 0); + $this->Logger()->Write(0 < $iLimit && $iLimit < \strlen($sResult) + ? \substr($sResult, 0, $iLimit).'...' : $sResult, \MailSo\Log\Enumerations\Type::INFO, 'AJAX'); + } + + return $sResult; + } + + /** + * @return string + */ + public function ServiceAppend() + { + @\ob_start(); + $bResponse = false; + $oException = null; + try + { + if (\method_exists($this->oActions, 'Append') && + \is_callable(array($this->oActions, 'Append'))) + { + $this->oActions->SetActionParams($this->oHttp->GetPostAsArray(), 'Append'); + $bResponse = \call_user_func(array($this->oActions, 'Append')); + } + } + catch (\Exception $oException) + { + $bResponse = false; + } + + @\header('Content-Type: text/plain; charset=utf-8'); + $sResult = true === $bResponse ? '1' : '0'; + + $sObResult = @\ob_get_clean(); + if (0 < \strlen($sObResult)) + { + $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); + } + + if ($oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR); + } + + $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPEND'); + + return $sResult; + } + + /** + * @param string $sAction + * + * @return string + */ + private function privateUpload($sAction) + { + @\ob_start(); + $aResponseItem = null; + try + { + if (\method_exists($this->oActions, $sAction) && + \is_callable(array($this->oActions, $sAction))) + { + $this->oActions->SetActionParams($this->oHttp->GetQueryAsArray(), $sAction); + + $aResponseItem = \call_user_func(array($this->oActions, $sAction)); + } + + if (!is_array($aResponseItem)) + { + throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::UnknownError); + } + } + catch (\Exception $oException) + { + $aResponseItem = $this->oActions->ExceptionResponse($sAction, $oException); + } + + if ('iframe' === $this->oHttp->GetPost('jua-post-type', '')) + { + @\header('Content-Type: text/html; charset=utf-8'); + } + else + { + @\header('Content-Type: application/json; charset=utf-8'); + } + + $this->Plugins()->RunHook('filter.upload-response', array(&$aResponseItem)); + $sResult = \MailSo\Base\Utils::Php2js($aResponseItem); + + $sObResult = @\ob_get_clean(); + if (0 < \strlen($sObResult)) + { + $this->Logger()->Write($sObResult, \MailSo\Log\Enumerations\Type::ERROR, 'OB-DATA'); + } + + $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'UPLOAD'); + + return $sResult; + } + + /** + * @return string + */ + public function ServiceUpload() + { + return $this->privateUpload('Upload'); + } + + /** + * @return string + */ + public function ServiceUploadBackground() + { + return $this->privateUpload('UploadBackground'); + } + + /** + * @return string + */ + public function ServiceRaw() + { + $sResult = ''; + $sRawError = ''; + $sAction = empty($this->aPaths[2]) ? '' : $this->aPaths[2]; + $oException = null; + + try + { + $sRawError = 'Invalid action'; + if (0 !== \strlen($sAction)) + { + $sMethodName = 'Raw'.$sAction; + if (\method_exists($this->oActions, $sMethodName)) + { + $sRawError = ''; + $this->oActions->SetActionParams(array( + 'RawKey' => empty($this->aPaths[3]) ? '' : $this->aPaths[3] + ), $sMethodName); + + if (!\call_user_func(array($this->oActions, $sMethodName))) + { + $sRawError = 'False result'; + } + else + { + $sRawError = ''; + } + } + } + } + catch (\RainLoop\Exceptions\ClientException $oException) + { + $sRawError = 'Exception as result'; + switch ($oException->getCode()) + { + case \RainLoop\Notifications::AuthError: + $sRawError = 'Authentication failed'; + break; + } + } + catch (\Exception $oException) + { + $sRawError = 'Exception as result'; + } + + if (0 < \strlen($sRawError)) + { + $this->oActions->Logger()->Write($sRawError, \MailSo\Log\Enumerations\Type::ERROR); + } + + if ($oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR, 'RAW'); + } + + return $sResult; + } + + /** + * @return string + */ + public function ServiceLang() + { + $sResult = ''; + @\header('Content-Type: application/javascript; charset=utf-8'); + + if (!empty($this->aPaths[2])) + { + $sLanguage = $this->oActions->ValidateLanguage($this->aPaths[2]); + + $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); + if (!empty($sLanguage) && $bCacheEnabled) + { + $this->oActions->verifyCacheByKey($this->sQuery); + } + + $sCacheFileName = ''; + if ($bCacheEnabled) + { + $sCacheFileName = 'LANG:'.$this->oActions->Plugins()->Hash().$sLanguage.APP_VERSION; + $sResult = $this->Cacher()->Get($sCacheFileName); + } + + if (0 === \strlen($sResult)) + { + $sResult = $this->compileLanguage($sLanguage, false); + if ($bCacheEnabled && 0 < \strlen($sCacheFileName)) + { + $this->Cacher()->Set($sCacheFileName, $sResult); + } + } + + if ($bCacheEnabled) + { + $this->oActions->cacheByKey($this->sQuery); + } + } + + return $sResult; + } + + /** + * @return string + */ + public function ServiceTemplates() + { + $sResult = ''; + @\header('Content-Type: application/javascript; charset=utf-8'); + + $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); + if ($bCacheEnabled) + { + $this->oActions->verifyCacheByKey($this->sQuery); + } + + $sCacheFileName = ''; + if ($bCacheEnabled) + { + $sCacheFileName = 'TEMPLATES:'.$this->oActions->Plugins()->Hash().APP_VERSION; + $sResult = $this->Cacher()->Get($sCacheFileName); + } + + if (0 === \strlen($sResult)) + { + $sResult = $this->compileTemplates(false); + if ($bCacheEnabled && 0 < \strlen($sCacheFileName)) + { + $this->Cacher()->Set($sCacheFileName, $sResult); + } + } + + if ($bCacheEnabled) + { + $this->oActions->cacheByKey($this->sQuery); + } + + return $sResult; + } + + /** + * @return string + */ + public function ServicePlugins() + { + $sResult = ''; + $bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2]; + + @\header('Content-Type: application/javascript; charset=utf-8'); + + $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); + if ($bCacheEnabled) + { + $this->oActions->verifyCacheByKey($this->sQuery); + } + + $sCacheFileName = ''; + if ($bCacheEnabled) + { + $sCacheFileName = 'PLUGIN:'.$this->oActions->Plugins()->Hash().APP_VERSION; + $sResult = $this->Cacher()->Get($sCacheFileName); + } + + if (0 === strlen($sResult)) + { + $sResult = $this->Plugins()->CompileJs($bAdmin); + if ($bCacheEnabled && 0 < \strlen($sCacheFileName)) + { + $this->Cacher()->Set($sCacheFileName, $sResult); + } + } + + if ($bCacheEnabled) + { + $this->oActions->cacheByKey($this->sQuery); + } + + return $sResult; + } + + /** + * @return string + */ + public function ServiceCss() + { + $sResult = ''; + $bCustom = false; + $oAccount = null; + $oSettings = null; + + $bAdmin = !empty($this->aPaths[2]) && 'Admin' === $this->aPaths[2]; + $bJson = !empty($this->aPaths[7]) && 'Json' === $this->aPaths[7]; + + if ($bJson) + { + @\header('Content-Type: application/json; charset=utf-8'); + } + else + { + @\header('Content-Type: text/css; charset=utf-8'); + } + + $sTheme = ''; + if (!empty($this->aPaths[4])) + { + $sTheme = $this->oActions->ValidateTheme($this->aPaths[4]); + if ('Custom' === $sTheme && !empty($this->aPaths[1]) && '0' !== $this->aPaths[1]) + { + $bCustom = true; + $oAccount = $this->oActions->GetAccount(false); + if ($oAccount) + { + $oSettings = $this->oActions->SettingsProvider()->Load($oAccount); + } + } + + $bCacheEnabled = $this->Config()->Get('labs', 'cache_system_data', true); + if ($bCacheEnabled && !$bCustom) + { + $this->oActions->verifyCacheByKey($this->sQuery); + } + + $sCacheFileName = ''; + if ($bCacheEnabled && !$bCustom) + { + $sCacheFileName = 'THEMES/PLUGINS:'.$sTheme.':'.$this->Plugins()->Hash(); + $sResult = $this->Cacher()->Get($sCacheFileName); + } + + if (0 === \strlen($sResult)) + { + try + { + include_once APP_VERSION_ROOT_PATH.'app/libraries/lessphp/ctype.php'; + include_once APP_VERSION_ROOT_PATH.'app/libraries/lessphp/lessc.inc.php'; + + $oLess = new \lessc(); + $oLess->setFormatter('compressed'); + + $aResult = array(); + + $sThemeValuesFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/values.less'; + if ($bCustom) + { + $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-light.less'; + if ($oSettings) + { + if (\RainLoop\Enumerations\CustomThemeType::LIGHT === (string) $oSettings->GetConf('CustomThemeType', \RainLoop\Enumerations\CustomThemeType::LIGHT)) + { + $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-light.less'; + } + else + { + $sThemeFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/custom-values-dark.less'; + } + } + } + else + { + $sThemeFile = APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/styles.less'; + } + + $sThemeTemplateFile = APP_VERSION_ROOT_PATH.'app/templates/Themes/template.less'; + + if (\file_exists($sThemeFile) && \file_exists($sThemeTemplateFile) && \file_exists($sThemeValuesFile)) + { + $aResult[] = '@base: "'.APP_WEB_PATH.'themes/'.$sTheme.'/";'; + $aResult[] = \file_get_contents($sThemeValuesFile); + $aResult[] = \file_get_contents($sThemeFile); + $aResult[] = \file_get_contents($sThemeTemplateFile); + + if (\file_exists(APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/ext.less')) + { + $aResult[] = \file_get_contents(APP_VERSION_ROOT_PATH.'themes/'.$sTheme.'/ext.less'); + } + } + + $aResult[] = $this->Plugins()->CompileCss($bAdmin); + + $sResult = $oLess->compile(\implode("\n", $aResult)); + + if ($bCustom && $oAccount) + { + $mData = $this->oActions->StorageProvider()->Get($oAccount, StorageType::USER, 'CustomThemeBackground', ''); + if (!empty($mData) && 'data:' === \substr($mData, 0, 5)) + { + $sResult = \str_replace('background-image:link', 'background-image:url("'.$mData.'")', $sResult); + } + } + + if ($bCacheEnabled && !$bCustom) + { + if (0 < \strlen($sCacheFileName)) + { + $this->Cacher()->Set($sCacheFileName, $sResult); + } + } + } + catch (\Exception $oException) + { + $this->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR, 'LESS'); + } + } + + if ($bCacheEnabled && !$bCustom) + { + $this->oActions->cacheByKey($this->sQuery); + } + } + + return $bJson ? \MailSo\Base\Utils::Php2js(array($sTheme, $sResult)) : $sResult; + } + + /** + * @return string + */ + public function ServiceSocialGoogle() + { + return $this->oActions->Social()->GooglePopupService(); + } + + /** + * @return string + */ + public function ServiceSocialFacebook() + { + return $this->oActions->Social()->FacebookPopupService(); + } + + /** + * @return string + */ + public function ServiceSocialTwitter() + { + return $this->oActions->Social()->TwitterPopupService(); + } + + /** + * @return string + */ + public function ServiceAppData() + { + return $this->localAppData(false); + } + + /** + * @return string + */ + public function ServiceAdminAppData() + { + return $this->localAppData(true); + } + + /** + * @return string + */ + public function ServiceNoScript() + { + return $this->localError($this->oActions->StaticI18N('STATIC/NO_SCRIPT_TITLE'), $this->oActions->StaticI18N('STATIC/NO_SCRIPT_DESC')); + } + + /** + * @return string + */ + public function ServiceNoCookie() + { + return $this->localError($this->oActions->StaticI18N('STATIC/NO_COOKIE_TITLE'), $this->oActions->StaticI18N('STATIC/NO_COOKIE_DESC')); + } + + /** + * @return string + */ + public function ServiceBadBrowser() + { + $sTitle = $this->oActions->StaticI18N('STATIC/BAD_BROWSER_TITLE'); + $sDesc = \nl2br($this->oActions->StaticI18N('STATIC/BAD_BROWSER_DESC')); + + @\header('Content-Type: text/html; charset=utf-8'); + return \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/BadBrowser.html'), array( + '{{BaseWebStaticPath}}' => APP_WEB_STATIC_PATH, + '{{ErrorTitle}}' => $sTitle, + '{{ErrorHeader}}' => $sTitle, + '{{ErrorDesc}}' => $sDesc + )); + } + + /** + * @return string + */ + public function ServicePing() + { + @\header('Content-Type: text/plain; charset=utf-8'); + $this->oActions->Logger()->Write('Pong', \MailSo\Log\Enumerations\Type::INFO, 'PING'); + return 'Pong'; + } + + /** + * @return string + */ + public function ServiceInfo() + { + if ($this->oActions->IsAdminLoggined(false)) + { + @\header('Content-Type: text/html; charset=utf-8'); + \phpinfo(); + } + } + + /** + * @return string + */ + public function ServiceExternalLogin() + { + if ($this->oActions->Config()->Get('labs', 'allow_external_login', false)) + { + $oException = null; + try + { + $sEmail = trim($this->oHttp->GetRequest('Email', '')); + $sLogin = trim($this->oHttp->GetRequest('Login', '')); + $sPassword = $this->oHttp->GetRequest('Password', ''); + + $this->oActions->Logger()->AddSecret($sPassword); + + if (0 === \strlen($sLogin)) + { + $sLogin = $sEmail; + } + + $oAccount = $this->oActions->LoginProcess($sEmail, $sLogin, $sPassword); + $this->oActions->AuthProcess($oAccount); + } + catch (\Exception $oException) + { + $this->oActions->Logger()->WriteException($oException); + } + } + + $this->oActions->Location('./'); + return ''; + } + + /** + * @return string + */ + public function ServiceChange() + { + if ($this->Config()->Get('webmail', 'allow_additional_accounts', true)) + { + $oAccountToLogin = null; + $sEmail = empty($this->aPaths[2]) ? '' : \strtolower(\urldecode(\trim($this->aPaths[2]))); + if (!empty($sEmail)) + { + $oAccount = $this->oActions->GetAccount(); + if ($oAccount) + { + $aAccounts = $this->oActions->GetAccounts($oAccount); + if (isset($aAccounts[$sEmail])) + { + $oAccountToLogin = $this->oActions->GetAccountFromCustomToken($aAccounts[$sEmail], false, false); + } + } + } + + if ($oAccountToLogin) + { + $this->oActions->AuthProcess($oAccountToLogin); + } + } + + $this->oActions->Location('./'); + return ''; + } + + /** + * @param string $sTitle + * @param string $sDesc + * + * @return string + */ + private function localError($sTitle, $sDesc) + { + @header('Content-Type: text/html; charset=utf-8'); + return $this->oActions->ErrorTemplates($sTitle, \nl2br($sDesc)); + } + + /** + * @param bool $bAdmin = true + * + * @return string + */ + private function localAppData($bAdmin = false) + { + @\header('Content-Type: application/javascript; charset=utf-8'); + @\header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); + @\header('Last-Modified: '.\gmdate('D, d M Y H:i:s').' GMT'); + @\header('Cache-Control: no-store, no-cache, must-revalidate'); + @\header('Cache-Control: post-check=0, pre-check=0', false); + @\header('Pragma: no-cache'); + + $sAuthAccountHash = ''; + if (!$bAdmin) + { + $sAuthAccountHash = $this->oActions->GetSpecAuthTokenWithDeletion(); + if (empty($sAuthAccountHash)) + { + $sAuthAccountHash = $this->oActions->GetSpecAuthToken(); + } + + if (empty($sAuthAccountHash)) + { + $sSignMeToken = \RainLoop\Utils::GetCookie(\RainLoop\Actions::AUTH_SIGN_ME_TOKEN_KEY, ''); + if (!empty($sSignMeToken)) + { + $oAccount = $this->oActions->GetAccountFromCustomToken($this->StorageProvider()->Get(null, + \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY, + 'SignMe/UserToken/'.$sSignMeToken + ), false, false); + + if ($oAccount) + { + $this->oActions->AuthProcess($oAccount); + $sAuthAccountHash = $this->oActions->GetSpecAuthToken(); + } + } + } + + $this->oActions->SetSpecAuthToken($sAuthAccountHash); + } + + $sResult = $this->compileAppData($this->oActions->AppData($bAdmin, $sAuthAccountHash), false); + + $this->Logger()->Write($sResult, \MailSo\Log\Enumerations\Type::INFO, 'APPDATA'); + + return $sResult; + } + + /** + * @param bool $bAdmin = false + * @param bool $bWrapByScriptTag = true + * + * @return string + */ + private function compileTemplates($bAdmin = false, $bWrapByScriptTag = false) + { + $sHtml = \RainLoop\Utils::CompileTemplates(APP_VERSION_ROOT_PATH.'app/templates/Views', $this->oActions). + $this->oActions->Plugins()->CompileTemplate($bAdmin); + + return + ($bWrapByScriptTag ? '' : '') + ; + } + + /** + * @param string $sLanguage + * @param bool $bWrapByScriptTag = true + * + * @return string + */ + private function compileLanguage($sLanguage, $bWrapByScriptTag = true) + { + $aResultLang = array(); + + $sMoment = 'window.moment && window.moment.lang && window.moment.lang(\'en\');'; + $sMomentFileName = APP_VERSION_ROOT_PATH.'app/i18n/moment/'.$sLanguage.'.js'; + if (\file_exists($sMomentFileName)) + { + $sMoment = \file_get_contents($sMomentFileName); + $sMoment = \preg_replace('/\/\/[^\n]+\n/', '', $sMoment); + } + + \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'app/i18n/langs.ini', $aResultLang); + \RainLoop\Utils::ReadAndAddLang(APP_VERSION_ROOT_PATH.'langs/'.$sLanguage.'.ini', $aResultLang); + + $this->Plugins()->ReadLang($sLanguage, $aResultLang); + + $sLangJs = ''; + $aLangKeys = \array_keys($aResultLang); + foreach ($aLangKeys as $sKey) + { + $sString = isset($aResultLang[$sKey]) ? $aResultLang[$sKey] : $sKey; + + $sLangJs .= '"'.\str_replace('"', '\\"', \str_replace('\\', '\\\\', $sKey)).'":' + .'"'.\str_replace(array("\r", "\n", "\t"), array('\r', '\n', '\t'), + \str_replace('"', '\\"', \str_replace('\\', '\\\\', $sString))).'",'; + } + + $sResult = empty($sLangJs) ? 'null' : '{'.\substr($sLangJs, 0, -1).'}'; + + return + ($bWrapByScriptTag ? '' : '') + ; + } + + /** + * @param array $aAppData + * @param bool $bWrapByScriptTag = true + * + * @return string + */ + private function compileAppData($aAppData, $bWrapByScriptTag = true) + { + return + ($bWrapByScriptTag ? '' : '') + ; + } +} diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Settings.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Settings.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Settings.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Settings.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Social.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Social.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Social.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Social.php diff --git a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Utils.php b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Utils.php similarity index 95% rename from rainloop/v/1.3.9.485/app/libraries/RainLoop/Utils.php rename to rainloop/v/1.3.10.490/app/libraries/RainLoop/Utils.php index fa29a74df7..8c5b728c65 100644 --- a/rainloop/v/1.3.9.485/app/libraries/RainLoop/Utils.php +++ b/rainloop/v/1.3.10.490/app/libraries/RainLoop/Utils.php @@ -1,392 +1,409 @@ -isFile() ? \md5_file($oFile) : $oFile)); - } - } - - return $sResult; - } - - /** - * @param string $FileName - * @param array $aResultLang - * - * @return void - */ - public static function ReadAndAddLang($FileName, &$aResultLang) - { - if (\file_exists($FileName)) - { - $aLang = @\parse_ini_file($FileName, true); - if (\is_array($aLang)) - { - foreach ($aLang as $sKey => $mValue) - { - if (\is_array($mValue)) - { - foreach ($mValue as $sSecKey => $mSecValue) - { - $aResultLang[$sKey.'/'.$sSecKey] = $mSecValue; - } - } - else - { - $aResultLang[$sKey] = $mValue; - } - } - } - } - } - - /** - * @param string $sDir - * @param string $sType = '' - * @return array - */ - public static function FolderFiles($sDir, $sType = '') - { - $aResult = array(); - if (@\is_dir($sDir)) - { - if (false !== ($rDirHandle = @\opendir($sDir))) - { - while (false !== ($sFile = @\readdir($rDirHandle))) - { - if (empty($sType) || $sType === \substr($sFile, -\strlen($sType))) - { - if (\is_file($sDir.'/'.$sFile)) - { - $aResult[] = $sFile; - } - } - } - - @\closedir($rDirHandle); - } - } - - return $aResult; - } - - /** - * @param string $sHtml - * - * @return string - */ - public static function ClearHtmlOutput($sHtml) - { -// return $sHtml; - return \str_replace('> <', '><', - \preg_replace('/[\s]+ /i', ' ', - \preg_replace('/ [\s]+/i', ' ', - \preg_replace('/[\r\n\t]+/', ' ', - $sHtml - )))); - } - - /** - * @param string $sKey - * @return bool - */ - public static function FastCheck($sKey) - { - $bResult = false; - - $aMatches = array(); - if (!empty($sKey) && 0 < \strlen($sKey) && \preg_match('/^(RL[\d]+)\-(.+)\-([^\-]+)$/', $sKey, $aMatches) && 3 === \count($aMatches)) - { - $bResult = $aMatches[3] === \strtoupper(\base_convert(\crc32(\md5( - $aMatches[1].'-'.$aMatches[2].'-')), 10, 32)); - } - - return $bResult; - } - - /** - * @param string $sDirName - * - * @return string - */ - public static function CompileTemplates($sDirName, $oAction) - { - $sResult = ''; - if (\file_exists($sDirName)) - { - $aList = \RainLoop\Utils::FolderFiles($sDirName, '.html'); - - foreach ($aList as $sName) - { - $sTemplateName = \substr($sName, 0, -5); - $sResult .= ''; - } - - $sResult = \trim($sResult); - } - - return $sResult; - } - - /** - * @param string $sName - * @param mixed $mDefault = null - * @return mixed - */ - public static function GetCookie($sName, $mDefault = null) - { - if (null === self::$Cookies) - { - self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); - } - - return isset(self::$Cookies[$sName]) ? self::$Cookies[$sName] : $mDefault; - } - - public static function SetCookie($sName, $sValue = '', $iExpire = 0, $sPath = '/', $sDomain = '', $sSecure = false, $bHttpOnly = false) - { - if (null === self::$Cookies) - { - self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); - } - - self::$Cookies[$sName] = $sValue; - @\setcookie($sName, $sValue, $iExpire, $sPath, $sDomain, $sSecure, $bHttpOnly); - } - - public static function ClearCookie($sName) - { - if (null === self::$Cookies) - { - self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); - } - - unset(self::$Cookies[$sName]); - @\setcookie($sName, '', \time() - 3600 * 24 * 30, '/'); - } - - /** - * @return array - */ - public static function ServicesPics() - { - return array( - 'ebay.com' => 'ebay.jpg', - 'reply.ebay.com' => 'ebay.jpg', - 'reply1.ebay.com' => 'ebay.jpg', - 'reply2.ebay.com' => 'ebay.jpg', - 'reply3.ebay.com' => 'ebay.jpg', - - 'facebook.com' => 'facebook.png', - 'facebookmail.com' => 'facebook.png', - - 'cnet.online.com' => 'cnet.jpg', - 'github.com' => 'github.png', - 'steampowered.com' => 'steam.png', - 'myspace.com' => 'myspace.png', - 'new.myspace.com' => 'myspace.png', - 'youtube.com' => 'youtube.gif', - 'amazon.com' => 'amazon.png', - 'ted.com' => 'ted.png', - 'icloud.com' => 'icloud.jpg', - 'google.com' => 'google.png', - 'plus.google.com' => 'google-plus.png', - - 'email.microsoft.com' => 'microsoft.jpg', - 'microsoftonline.com' => 'microsoft.jpg', - 'microsoft.com' => 'microsoft.jpg', - - 'paypal.com' => 'paypal.jpg', - 'intl.paypal.com' => 'paypal.jpg', - 'e.paypal.com' => 'paypal.jpg', - - 'ea.com' => 'ea.png', - 'em.ea.com' => 'ea.png', - 'battlefieldheroes.com' => 'ea.png', - - 'battle.net' => 'battle.net.png', - 'blizzard.com' => 'battle.net.png', - 'email.blizzard.com' => 'battle.net.png', - 'battlefieldheroes.com' => 'battle.net.png', - - 'twitter.com' => 'twitter.jpg', - 'postmaster.twitter.com' => 'twitter.jpg', - - 'skype.com' => 'skype.png', - 'email.skype.com' => 'skype.png', - - 'apple.com' => 'apple.jpg', - 'id.apple.com' => 'apple.jpg', - - 'onlive.com' => 'onlive.png', - 'news.onlive.com' => 'onlive.png', - - 'asana.com' => 'asana.png', - 'connect.asana.com' => 'asana.png', - ); - } - - public static function CustomBaseConvert($sNumberInput, $sFromBaseInput = '0123456789', $sToBaseInput = '0123456789') - { - if ($sFromBaseInput === $sToBaseInput) - { - return $sNumberInput; - } - - $mFromBase = \str_split($sFromBaseInput, 1); - $mToBase = \str_split($sToBaseInput, 1); - $aNumber = \str_split($sNumberInput, 1); - $iFromLen = \strlen($sFromBaseInput); - $iToLen = \strlen($sToBaseInput); - $numberLen = \strlen($sNumberInput); - $mRetVal = ''; - - if ($sToBaseInput === '0123456789') - { - $mRetVal = 0; - for ($iIndex = 1; $iIndex <= $numberLen; $iIndex++) - { - $mRetVal = \bcadd($mRetVal, \bcmul(\array_search($aNumber[$iIndex - 1], $mFromBase), \bcpow($iFromLen, $numberLen - $iIndex))); - } - - return $mRetVal; - } - - if ($sFromBaseInput != '0123456789') - { - $sBase10 = \RainLoop\Utils::CustomBaseConvert($sNumberInput, $sFromBaseInput, '0123456789'); - } - else - { - $sBase10 = $sNumberInput; - } - - if ($sBase10 < \strlen($sToBaseInput)) - { - return $mToBase[$sBase10]; - } - - while ($sBase10 !== '0') - { - $mRetVal = $mToBase[\bcmod($sBase10, $iToLen)].$mRetVal; - $sBase10 = \bcdiv($sBase10, $iToLen, 0); - } - - return $mRetVal; - } +isFile() ? \md5_file($oFile) : $oFile)); + } + } + + return $sResult; + } + + /** + * @param string $FileName + * @param array $aResultLang + * + * @return void + */ + public static function ReadAndAddLang($FileName, &$aResultLang) + { + if (\file_exists($FileName)) + { + $aLang = @\parse_ini_file($FileName, true); + if (\is_array($aLang)) + { + foreach ($aLang as $sKey => $mValue) + { + if (\is_array($mValue)) + { + foreach ($mValue as $sSecKey => $mSecValue) + { + $aResultLang[$sKey.'/'.$sSecKey] = $mSecValue; + } + } + else + { + $aResultLang[$sKey] = $mValue; + } + } + } + } + } + + /** + * @param string $sDir + * @param string $sType = '' + * @return array + */ + public static function FolderFiles($sDir, $sType = '') + { + $aResult = array(); + if (@\is_dir($sDir)) + { + if (false !== ($rDirHandle = @\opendir($sDir))) + { + while (false !== ($sFile = @\readdir($rDirHandle))) + { + if (empty($sType) || $sType === \substr($sFile, -\strlen($sType))) + { + if (\is_file($sDir.'/'.$sFile)) + { + $aResult[] = $sFile; + } + } + } + + @\closedir($rDirHandle); + } + } + + return $aResult; + } + + /** + * @param string $sHtml + * + * @return string + */ + public static function ClearHtmlOutput($sHtml) + { +// return $sHtml; + return \str_replace('> <', '><', + \preg_replace('/[\s]+ /i', ' ', + \preg_replace('/ [\s]+/i', ' ', + \preg_replace('/[\r\n\t]+/', ' ', + $sHtml + )))); + } + + /** + * @param string $sKey + * @return bool + */ + public static function FastCheck($sKey) + { + $bResult = false; + + $aMatches = array(); + if (!empty($sKey) && 0 < \strlen($sKey) && \preg_match('/^(RL[\d]+)\-(.+)\-([^\-]+)$/', $sKey, $aMatches) && 3 === \count($aMatches)) + { + $bResult = $aMatches[3] === \strtoupper(\base_convert(\crc32(\md5( + $aMatches[1].'-'.$aMatches[2].'-')), 10, 32)); + } + + return $bResult; + } + + /** + * @param string $sDirName + * + * @return string + */ + public static function CompileTemplates($sDirName, $oAction) + { + $sResult = ''; + if (\file_exists($sDirName)) + { + $aList = \RainLoop\Utils::FolderFiles($sDirName, '.html'); + + foreach ($aList as $sName) + { + $sTemplateName = \substr($sName, 0, -5); + $sResult .= ''; + } + + $sResult = \trim($sResult); + } + + return $sResult; + } + + /** + * @param string $sName + * @param mixed $mDefault = null + * @return mixed + */ + public static function GetCookie($sName, $mDefault = null) + { + if (null === self::$Cookies) + { + self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + } + + return isset(self::$Cookies[$sName]) ? self::$Cookies[$sName] : $mDefault; + } + + public static function SetCookie($sName, $sValue = '', $iExpire = 0, $sPath = '/', $sDomain = '', $sSecure = false, $bHttpOnly = false) + { + if (null === self::$Cookies) + { + self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + } + + self::$Cookies[$sName] = $sValue; + @\setcookie($sName, $sValue, $iExpire, $sPath, $sDomain, $sSecure, $bHttpOnly); + } + + public static function ClearCookie($sName) + { + if (null === self::$Cookies) + { + self::$Cookies = is_array($_COOKIE) ? $_COOKIE : array(); + } + + unset(self::$Cookies[$sName]); + @\setcookie($sName, '', \time() - 3600 * 24 * 30, '/'); + } + + /** + * @return array + */ + public static function ServicesPics() + { + return array( + 'ebay.com' => 'ebay.jpg', + 'reply.ebay.com' => 'ebay.jpg', + 'reply1.ebay.com' => 'ebay.jpg', + 'reply2.ebay.com' => 'ebay.jpg', + 'reply3.ebay.com' => 'ebay.jpg', + + 'facebook.com' => 'facebook.png', + 'facebookmail.com' => 'facebook.png', + + 'cnet.online.com' => 'cnet.jpg', + 'github.com' => 'github.png', + 'steampowered.com' => 'steam.png', + 'myspace.com' => 'myspace.png', + 'new.myspace.com' => 'myspace.png', + 'youtube.com' => 'youtube.gif', + 'amazon.com' => 'amazon.png', + 'ted.com' => 'ted.png', + 'icloud.com' => 'icloud.jpg', + 'google.com' => 'google.png', + 'plus.google.com' => 'google-plus.png', + + 'email.microsoft.com' => 'microsoft.jpg', + 'microsoftonline.com' => 'microsoft.jpg', + 'microsoft.com' => 'microsoft.jpg', + + 'paypal.com' => 'paypal.jpg', + 'intl.paypal.com' => 'paypal.jpg', + 'e.paypal.com' => 'paypal.jpg', + + 'ea.com' => 'ea.png', + 'em.ea.com' => 'ea.png', + 'battlefieldheroes.com' => 'ea.png', + + 'battle.net' => 'battle.net.png', + 'blizzard.com' => 'battle.net.png', + 'email.blizzard.com' => 'battle.net.png', + 'battlefieldheroes.com' => 'battle.net.png', + + 'twitter.com' => 'twitter.jpg', + 'postmaster.twitter.com' => 'twitter.jpg', + + 'skype.com' => 'skype.png', + 'email.skype.com' => 'skype.png', + + 'apple.com' => 'apple.jpg', + 'id.apple.com' => 'apple.jpg', + + 'onlive.com' => 'onlive.png', + 'news.onlive.com' => 'onlive.png', + + 'asana.com' => 'asana.png', + 'connect.asana.com' => 'asana.png', + ); + } + + public static function CustomBaseConvert($sNumberInput, $sFromBaseInput = '0123456789', $sToBaseInput = '0123456789') + { + if ($sFromBaseInput === $sToBaseInput) + { + return $sNumberInput; + } + + $mFromBase = \str_split($sFromBaseInput, 1); + $mToBase = \str_split($sToBaseInput, 1); + $aNumber = \str_split($sNumberInput, 1); + $iFromLen = \strlen($sFromBaseInput); + $iToLen = \strlen($sToBaseInput); + $numberLen = \strlen($sNumberInput); + $mRetVal = ''; + + if ($sToBaseInput === '0123456789') + { + $mRetVal = 0; + for ($iIndex = 1; $iIndex <= $numberLen; $iIndex++) + { + $mRetVal = \bcadd($mRetVal, \bcmul(\array_search($aNumber[$iIndex - 1], $mFromBase), \bcpow($iFromLen, $numberLen - $iIndex))); + } + + return $mRetVal; + } + + if ($sFromBaseInput != '0123456789') + { + $sBase10 = \RainLoop\Utils::CustomBaseConvert($sNumberInput, $sFromBaseInput, '0123456789'); + } + else + { + $sBase10 = $sNumberInput; + } + + if ($sBase10 < \strlen($sToBaseInput)) + { + return $mToBase[$sBase10]; + } + + while ($sBase10 !== '0') + { + $mRetVal = $mToBase[\bcmod($sBase10, $iToLen)].$mRetVal; + $sBase10 = \bcdiv($sBase10, $iToLen, 0); + } + + return $mRetVal; + } } \ No newline at end of file diff --git a/rainloop/v/1.3.9.485/app/libraries/facebook/base_facebook.php b/rainloop/v/1.3.10.490/app/libraries/facebook/base_facebook.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/facebook/base_facebook.php rename to rainloop/v/1.3.10.490/app/libraries/facebook/base_facebook.php diff --git a/rainloop/v/1.3.9.485/app/libraries/facebook/facebook.php b/rainloop/v/1.3.10.490/app/libraries/facebook/facebook.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/facebook/facebook.php rename to rainloop/v/1.3.10.490/app/libraries/facebook/facebook.php diff --git a/rainloop/v/1.3.9.485/app/libraries/facebook/fb_ca_chain_bundle.crt b/rainloop/v/1.3.10.490/app/libraries/facebook/fb_ca_chain_bundle.crt similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/facebook/fb_ca_chain_bundle.crt rename to rainloop/v/1.3.10.490/app/libraries/facebook/fb_ca_chain_bundle.crt diff --git a/rainloop/v/1.3.9.485/app/libraries/lessphp/LICENSE b/rainloop/v/1.3.10.490/app/libraries/lessphp/LICENSE similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/lessphp/LICENSE rename to rainloop/v/1.3.10.490/app/libraries/lessphp/LICENSE diff --git a/rainloop/v/1.3.9.485/app/libraries/lessphp/README.md b/rainloop/v/1.3.10.490/app/libraries/lessphp/README.md similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/lessphp/README.md rename to rainloop/v/1.3.10.490/app/libraries/lessphp/README.md diff --git a/rainloop/v/1.3.9.485/app/libraries/lessphp/ctype.php b/rainloop/v/1.3.10.490/app/libraries/lessphp/ctype.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/lessphp/ctype.php rename to rainloop/v/1.3.10.490/app/libraries/lessphp/ctype.php diff --git a/rainloop/v/1.3.9.485/app/libraries/lessphp/lessc.inc.php b/rainloop/v/1.3.10.490/app/libraries/lessphp/lessc.inc.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/lessphp/lessc.inc.php rename to rainloop/v/1.3.10.490/app/libraries/lessphp/lessc.inc.php diff --git a/rainloop/v/1.3.9.485/app/libraries/pclzip/gnu-lgpl.txt b/rainloop/v/1.3.10.490/app/libraries/pclzip/gnu-lgpl.txt similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/pclzip/gnu-lgpl.txt rename to rainloop/v/1.3.10.490/app/libraries/pclzip/gnu-lgpl.txt diff --git a/rainloop/v/1.3.9.485/app/libraries/pclzip/pclzip.lib.php b/rainloop/v/1.3.10.490/app/libraries/pclzip/pclzip.lib.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/pclzip/pclzip.lib.php rename to rainloop/v/1.3.10.490/app/libraries/pclzip/pclzip.lib.php diff --git a/rainloop/v/1.3.9.485/app/libraries/pclzip/readme.txt b/rainloop/v/1.3.10.490/app/libraries/pclzip/readme.txt similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/pclzip/readme.txt rename to rainloop/v/1.3.10.490/app/libraries/pclzip/readme.txt diff --git a/rainloop/v/1.3.9.485/app/libraries/tmhOAuth/LICENSE b/rainloop/v/1.3.10.490/app/libraries/tmhOAuth/LICENSE similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/tmhOAuth/LICENSE rename to rainloop/v/1.3.10.490/app/libraries/tmhOAuth/LICENSE diff --git a/rainloop/v/1.3.9.485/app/libraries/tmhOAuth/README.md b/rainloop/v/1.3.10.490/app/libraries/tmhOAuth/README.md similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/tmhOAuth/README.md rename to rainloop/v/1.3.10.490/app/libraries/tmhOAuth/README.md diff --git a/rainloop/v/1.3.9.485/app/libraries/tmhOAuth/cacert.pem b/rainloop/v/1.3.10.490/app/libraries/tmhOAuth/cacert.pem similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/tmhOAuth/cacert.pem rename to rainloop/v/1.3.10.490/app/libraries/tmhOAuth/cacert.pem diff --git a/rainloop/v/1.3.9.485/app/libraries/tmhOAuth/tmhOAuth.php b/rainloop/v/1.3.10.490/app/libraries/tmhOAuth/tmhOAuth.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/tmhOAuth/tmhOAuth.php rename to rainloop/v/1.3.10.490/app/libraries/tmhOAuth/tmhOAuth.php diff --git a/rainloop/v/1.3.9.485/app/libraries/tmhOAuth/tmhUtilities.php b/rainloop/v/1.3.10.490/app/libraries/tmhOAuth/tmhUtilities.php similarity index 100% rename from rainloop/v/1.3.9.485/app/libraries/tmhOAuth/tmhUtilities.php rename to rainloop/v/1.3.10.490/app/libraries/tmhOAuth/tmhUtilities.php diff --git a/rainloop/v/1.3.9.485/app/templates/BadBrowser.html b/rainloop/v/1.3.10.490/app/templates/BadBrowser.html similarity index 100% rename from rainloop/v/1.3.9.485/app/templates/BadBrowser.html rename to rainloop/v/1.3.10.490/app/templates/BadBrowser.html diff --git a/rainloop/v/1.3.9.485/app/templates/Error.html b/rainloop/v/1.3.10.490/app/templates/Error.html similarity index 100% rename from rainloop/v/1.3.9.485/app/templates/Error.html rename to rainloop/v/1.3.10.490/app/templates/Error.html diff --git a/rainloop/v/1.3.9.485/app/templates/Index.html b/rainloop/v/1.3.10.490/app/templates/Index.html similarity index 100% rename from rainloop/v/1.3.9.485/app/templates/Index.html rename to rainloop/v/1.3.10.490/app/templates/Index.html diff --git a/rainloop/v/1.3.9.485/app/templates/Themes/custom-values-dark.less b/rainloop/v/1.3.10.490/app/templates/Themes/custom-values-dark.less similarity index 100% rename from rainloop/v/1.3.9.485/app/templates/Themes/custom-values-dark.less rename to rainloop/v/1.3.10.490/app/templates/Themes/custom-values-dark.less diff --git a/rainloop/v/1.3.9.485/app/templates/Themes/custom-values-light.less b/rainloop/v/1.3.10.490/app/templates/Themes/custom-values-light.less similarity index 100% rename from rainloop/v/1.3.9.485/app/templates/Themes/custom-values-light.less rename to rainloop/v/1.3.10.490/app/templates/Themes/custom-values-light.less diff --git a/rainloop/v/1.3.9.485/app/templates/Themes/template.less b/rainloop/v/1.3.10.490/app/templates/Themes/template.less similarity index 96% rename from rainloop/v/1.3.9.485/app/templates/Themes/template.less rename to rainloop/v/1.3.10.490/app/templates/Themes/template.less index 16d8968696..6ca0ada708 100644 --- a/rainloop/v/1.3.9.485/app/templates/Themes/template.less +++ b/rainloop/v/1.3.10.490/app/templates/Themes/template.less @@ -1,148 +1,148 @@ - -// mixins +++ -.thm-linear-gradient-mixin(@start, @end) when (iscolor(@start)) and (iscolor(@end)) { - background-color: mix(@start, @end, 60%) !important; - background-image: -moz-linear-gradient(top, @start, @end) !important; // FF 3.6+ - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start), to(@end)) !important; // Safari 4+, Chrome 2+ - background-image: -webkit-linear-gradient(top, @start, @end) !important; // Safari 5.1+, Chrome 10+ - background-image: -o-linear-gradient(top, @start, @end !important); // Opera 11.10 - background-image: linear-gradient(to bottom, @start, @end) !important; // Standard, IE10 - background-repeat: repeat-x !important; - filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start),argb(@end))) !important; // IE9 and down -} - -.thm-border-radius(@radius) when (ispixel(@radius)) { - -webkit-border-radius: @radius !important; - -moz-border-radius: @radius !important; - border-radius: @radius !important; -} - -.thm-box-shadow(@shadow) { - -webkit-box-shadow: @shadow !important; - -moz-box-shadow: @shadow !important; - box-shadow: @shadow !important; -} -.thm-body-background-image(@value) when (isstring(@value)) { - background-image: url("@{base}@{value}") !important; -} -.thm-body-background-image(@value) when not (isstring(@value)) { - background-image: @value !important; -} -.thm-rgba-background-color(@simple, @rgba) when (@rgba = false) { - background-color: @simple !important; -} -.thm-rgba-background-color(@simple, @rgba) when not (@rgba = false) { - background-color: @simple !important; - background-color: @rgba !important; -} -// --- mixins - -.thm-body { - color: @main-color; - background-color: @main-background-color; - .thm-body-background-image(@main-background-image); -} - -.thm-loading { - color: @loading-color !important; - text-shadow: @loading-text-shadow !important; -} - -.thm-login { - color: @login-color !important; - border: @login-border !important; - .thm-rgba-background-color(@login-background-color, @login-rgba-background-color); - .thm-linear-gradient-mixin(@login-gradient-start, @login-gradient-end); - .thm-border-radius(@login-border-radius); - .thm-box-shadow(@login-box-shadow); - - .legend, .checkboxSignMe, g-ui-link { - color: @login-color !important; - } -} - -.g-ui-menu { - color: @dropdown-menu-color !important; - background-color: @dropdown-menu-background-color !important; -} - -.g-ui-menu .e-item > .e-link { - color: @dropdown-menu-color !important; - background-color: @dropdown-menu-background-color !important; - - > i { - color: @dropdown-menu-color !important; - } -} - -.g-ui-menu .e-item > .e-link:hover { - color: @dropdown-menu-hover-color !important; - background-color: @dropdown-menu-hover-background-color !important; - - > i { - color: @dropdown-menu-hover-color !important; - } -} - -.g-ui-menu .e-item.disable > .e-link, .g-ui-menu .e-item.disable > .e-link:hover { - color: @dropdown-menu-disable-color !important; - background-color: @dropdown-menu-background-color !important; - - > i { - color: @dropdown-menu-disable-color !important; - } -} - -.thm-message-list-top-toolbar, .thm-message-list-bottom-toolbar { - .thm-rgba-background-color(@message-list-toolbar-background-color, @message-list-toolbar-rgba-background-color); - .thm-linear-gradient-mixin(@message-list-toolbar-gradient-start, @message-list-toolbar-gradient-end); -} - -.thm-folders .e-link { - - color: @folders-disabled-color !important; - - &.selectable { - color: @folders-color !important; - } - - &.selectable:hover { - color: @folders-hover-color !important; - .thm-rgba-background-color(@folders-hover-background-color, @folders-hover-rgba-background-color); - } - - &.selectable.selected { - color: @folders-selected-color !important; - .thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color); - } - - &.selectable.droppableHover { - color: @folders-drop-color !important; - .thm-rgba-background-color(@folders-drop-background-color, @folders-drop-rgba-background-color); - } -} - -.thm-settings-menu .e-item { - - .e-link { - color: @settings-menu-disabled-color !important; - } - - &.selectable .e-link { - color: @settings-menu-color !important; - } - - &.selectable:hover .e-link { - .thm-rgba-background-color(@settings-menu-hover-background-color, @settings-menu-hover-rgba-background-color); - color: @settings-menu-hover-color !important; - } - - &.selectable.selected .e-link { - .thm-rgba-background-color(@settings-menu-selected-background-color, @settings-menu-selected-rgba-background-color); - color: @settings-menu-selected-color !important; - } -} - -.thm-message-view-background-color { - .thm-rgba-background-color(@message-background-color, @message-rgba-background-color); -} + +// mixins +++ +.thm-linear-gradient-mixin(@start, @end) when (iscolor(@start)) and (iscolor(@end)) { + background-color: mix(@start, @end, 60%) !important; + background-image: -moz-linear-gradient(top, @start, @end) !important; // FF 3.6+ + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start), to(@end)) !important; // Safari 4+, Chrome 2+ + background-image: -webkit-linear-gradient(top, @start, @end) !important; // Safari 5.1+, Chrome 10+ + background-image: -o-linear-gradient(top, @start, @end !important); // Opera 11.10 + background-image: linear-gradient(to bottom, @start, @end) !important; // Standard, IE10 + background-repeat: repeat-x !important; + filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start),argb(@end))) !important; // IE9 and down +} + +.thm-border-radius(@radius) when (ispixel(@radius)) { + -webkit-border-radius: @radius !important; + -moz-border-radius: @radius !important; + border-radius: @radius !important; +} + +.thm-box-shadow(@shadow) { + -webkit-box-shadow: @shadow !important; + -moz-box-shadow: @shadow !important; + box-shadow: @shadow !important; +} +.thm-body-background-image(@value) when (isstring(@value)) { + background-image: url("@{base}@{value}") !important; +} +.thm-body-background-image(@value) when not (isstring(@value)) { + background-image: @value !important; +} +.thm-rgba-background-color(@simple, @rgba) when (@rgba = false) { + background-color: @simple !important; +} +.thm-rgba-background-color(@simple, @rgba) when not (@rgba = false) { + background-color: @simple !important; + background-color: @rgba !important; +} +// --- mixins + +.thm-body { + color: @main-color; + background-color: @main-background-color; + .thm-body-background-image(@main-background-image); +} + +.thm-loading { + color: @loading-color !important; + text-shadow: @loading-text-shadow !important; +} + +.thm-login { + color: @login-color !important; + border: @login-border !important; + .thm-rgba-background-color(@login-background-color, @login-rgba-background-color); + .thm-linear-gradient-mixin(@login-gradient-start, @login-gradient-end); + .thm-border-radius(@login-border-radius); + .thm-box-shadow(@login-box-shadow); + + .legend, .checkboxSignMe, g-ui-link { + color: @login-color !important; + } +} + +.g-ui-menu { + color: @dropdown-menu-color !important; + background-color: @dropdown-menu-background-color !important; +} + +.g-ui-menu .e-item > .e-link { + color: @dropdown-menu-color !important; + background-color: @dropdown-menu-background-color !important; + + > i { + color: @dropdown-menu-color !important; + } +} + +.g-ui-menu .e-item > .e-link:hover { + color: @dropdown-menu-hover-color !important; + background-color: @dropdown-menu-hover-background-color !important; + + > i { + color: @dropdown-menu-hover-color !important; + } +} + +.g-ui-menu .e-item.disable > .e-link, .g-ui-menu .e-item.disable > .e-link:hover { + color: @dropdown-menu-disable-color !important; + background-color: @dropdown-menu-background-color !important; + + > i { + color: @dropdown-menu-disable-color !important; + } +} + +.thm-message-list-top-toolbar, .thm-message-list-bottom-toolbar { + .thm-rgba-background-color(@message-list-toolbar-background-color, @message-list-toolbar-rgba-background-color); + .thm-linear-gradient-mixin(@message-list-toolbar-gradient-start, @message-list-toolbar-gradient-end); +} + +.thm-folders .e-link { + + color: @folders-disabled-color !important; + + &.selectable { + color: @folders-color !important; + } + + &.selectable:hover { + color: @folders-hover-color !important; + .thm-rgba-background-color(@folders-hover-background-color, @folders-hover-rgba-background-color); + } + + &.selectable.selected { + color: @folders-selected-color !important; + .thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color); + } + + &.selectable.droppableHover { + color: @folders-drop-color !important; + .thm-rgba-background-color(@folders-drop-background-color, @folders-drop-rgba-background-color); + } +} + +.thm-settings-menu .e-item { + + .e-link { + color: @settings-menu-disabled-color !important; + } + + &.selectable .e-link { + color: @settings-menu-color !important; + } + + &.selectable:hover .e-link { + .thm-rgba-background-color(@settings-menu-hover-background-color, @settings-menu-hover-rgba-background-color); + color: @settings-menu-hover-color !important; + } + + &.selectable.selected .e-link { + .thm-rgba-background-color(@settings-menu-selected-background-color, @settings-menu-selected-rgba-background-color); + color: @settings-menu-selected-color !important; + } +} + +.thm-message-view-background-color { + .thm-rgba-background-color(@message-background-color, @message-rgba-background-color); +} diff --git a/rainloop/v/1.3.9.485/app/templates/Themes/values.less b/rainloop/v/1.3.10.490/app/templates/Themes/values.less similarity index 100% rename from rainloop/v/1.3.9.485/app/templates/Themes/values.less rename to rainloop/v/1.3.10.490/app/templates/Themes/values.less diff --git a/rainloop/v/1.3.9.485/app/templates/Views/AdminDomainListItem.html b/rainloop/v/1.3.10.490/app/templates/Views/AdminDomainListItem.html similarity index 100% rename from rainloop/v/1.3.9.485/app/templates/Views/AdminDomainListItem.html rename to rainloop/v/1.3.10.490/app/templates/Views/AdminDomainListItem.html diff --git a/rainloop/v/1.3.9.485/app/templates/Views/AdminDomains.html b/rainloop/v/1.3.10.490/app/templates/Views/AdminDomains.html similarity index 82% rename from rainloop/v/1.3.9.485/app/templates/Views/AdminDomains.html rename to rainloop/v/1.3.10.490/app/templates/Views/AdminDomains.html index 66e2a9c786..72a22c37ab 100644 --- a/rainloop/v/1.3.9.485/app/templates/Views/AdminDomains.html +++ b/rainloop/v/1.3.10.490/app/templates/Views/AdminDomains.html @@ -1,31 +1,31 @@ -
-- - - - Add Domain - -- List of domains webmail is allowed to access. -
-
++ + + + Add Domain + ++ List of domains webmail is allowed to access. +
+
- This domain is licensed for commercial use -
-- Subscription expires: - - -
-+ This domain is licensed for commercial use +
++ Subscription expires: + + +
+- - - - - | -- - - - | -
+ + + | ++ + + + | ++ + + + | +
'; - echo 'Your PHP version ('.PHP_VERSION.') is lower than the minimal required 5.3.0! (Error Code: 301)'; - echo '
'; - exit(301); - } - - if (in_array(false, $aRequirements)) - { - echo ''; - echo 'The following PHP extensions are not available in your PHP configuration! (Error Code: 302)'; - echo '
]*>/gmi,"\n__bq__start__\n").replace(/<\/blockquote>/gmi,"\n__bq__end__\n").replace(/]*>([\s\S]*?)<\/a>/gmi, -function(){return arguments&&1]*>/gm,"").replace(/>/gi,">").replace(/</gi,"<").replace(/&/gi,"&").replace(/&\w{2,6};/gi,"");return(a?d.splitPlainText(b):b).replace(/\n[ \t]+/gm,"\n").replace(/[\n]{3,}/gm,"\n\n").replace(/__bq__start__([\s\S]*)__bq__end__/gm,c).replace(/__bq__start__/gm,"").replace(/__bq__end__/gm,"")};u.prototype.getHtmlFromText=function(){return d.convertPlainTextToHtml(this.textarea.val())}; -u.prototype.switchToggle=function(){this.isHtml()?this.switchToPlain():this.switchToHtml()};u.prototype.switchToPlain=function(a){var a=d.isUnd(a)?!0:a,b=this.getTextFromHtml(),c=i.bind(function(a){a&&(this.toolbar.addClass("editorHideToolbar"),j(".editorSwitcher",this.toolbar).text(this.switcherLinkText(!1)),this.textarea.val(b),this.textarea.show(),this.htmlarea.hide(),this.fOnSwitch&&this.fOnSwitch(!1))},this);!a||0===d.trim(b).length?c(!0):c(h.confirm(this.oOptions.LangSwitcherConferm))};u.prototype.switcherLinkText= -function(a){return a?this.oOptions.LangSwitcherTextLabel:this.oOptions.LangSwitcherHtmlLabel};u.prototype.switchToHtml=function(){this.toolbar.removeClass("editorHideToolbar");j(".editorSwitcher",this.toolbar).text(this.switcherLinkText(!0));this.textarea.val(this.getHtmlFromText());this.updateHtmlArea();this.textarea.hide();this.htmlarea.show();this.fOnSwitch&&this.fOnSwitch(!0)};u.prototype.addButton=function(a,b){var c=this;j("").addClass("editorToolbarButtom").append(j('').addClass(a)).attr("title", -b).click(function(b){d.isUnd(u.htmlFunctions[a])?h.alert(a):u.htmlFunctions[a].apply(c,[j(this),b])}).appendTo(this.toolbar)};u.htmlInitToolbar=function(){if(!this.bOnlyPlain){this.addButton("bold","Bold");this.addButton("italic","Italic");this.addButton("underline","Underline");this.addButton("strikethrough","Strikethrough");this.addButton("removeformat","removeformat");this.addButton("justifyleft","justifyleft");this.addButton("justifycenter","justifycenter");this.addButton("justifyright","justifyright"); -this.addButton("horizontalrule","horizontalrule");this.addButton("orderedlist","orderedlist");this.addButton("unorderedlist","unorderedlist");this.addButton("indent","indent");this.addButton("outdent","outdent");this.addButton("forecolor","forecolor");var a=this;j("").addClass("editorSwitcher").text(a.switcherLinkText(!0)).click(function(){a.switchToggle()}).appendTo(a.toolbar)}};u.htmlInitEditor=function(){this.editor=this.htmlarea[0];this.editor.innerHTML=this.textarea.val()};u.htmlAttachEditorEvents= -function(){var a=this,b=function(b){if(b=(b&&b.originalEvent?b.originalEvent:b)||h.event){b.stopPropagation();b.preventDefault();var c=null,d=null;if((b=b.files||(b.dataTransfer?b.dataTransfer.files:null))&&1===b.length&&b[0]&&b[0].type&&0===b[0].type.indexOf("image/")){var d=b[0],c=new h.FileReader,e=d;c.onload=function(b){a.insertImage(b.target.result,e.name)};c.readAsDataURL(d)}}a.htmlarea.removeClass("editorDragOver")},c=function(){a.htmlarea.removeClass("editorDragOver")},d=function(b){b.stopPropagation(); -b.preventDefault();a.htmlarea.addClass("editorDragOver")},e=function(b){(b=b&&b.clipboardData?b.clipboardData:b&&b.originalEvent&&b.originalEvent.clipboardData?b.originalEvent.clipboardData:null)&&b.items&&i.each(b.items,function(b){if(b&&(b.type&&0===b.type.indexOf("image/"))&&b.getAsFile){var c=null,d=b.getAsFile();d&&(c=new h.FileReader,c.onload=function(b){a.insertImage(b.target.result,d.name)},c.readAsDataURL(d))}})};!this.bOnlyPlain&&(h.File&&h.FileReader&&h.FileList)&&(this.htmlarea.bind("dragover", -d),this.htmlarea.bind("dragleave",c),this.htmlarea.bind("drop",b),this.htmlarea.bind("paste",e))};for(var sa=u,ta=[],Va=[],Z=0,aa=0,Ia=0,Ja=0,aa="",Z=0;256>Z;Z+=85)aa=Z.toString(16),ta.push(1===aa.length?"0"+aa:aa);Ja=ta.length;for(Z=0;Z
";break;case g.ComposeType.Forward:L=r.fromToLine(!1,!0);t=r.toToLine(!1,!0);h=r.ccToLine(!1,!0);q="
"+q+"