mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-04 06:57:03 +03:00
Added "[labs] imap_show_login_alert" setting
Small fixes
This commit is contained in:
parent
f749d77fff
commit
43d1794423
81 changed files with 132 additions and 48 deletions
|
|
@ -16,4 +16,22 @@ namespace MailSo\Imap\Exceptions;
|
|||
* @package Imap
|
||||
* @subpackage Exceptions
|
||||
*/
|
||||
class NegativeResponseException extends \MailSo\Imap\Exceptions\ResponseException {}
|
||||
class NegativeResponseException extends \MailSo\Imap\Exceptions\ResponseException
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAlertFromStatus()
|
||||
{
|
||||
$sResult = '';
|
||||
|
||||
$oResponse = $this->GetLastResponse();
|
||||
if ($oResponse && $oResponse->IsStatusResponse && !empty($oResponse->HumanReadable) &&
|
||||
isset($oResponse->OptionalResponse[0]) && 'ALERT' === $oResponse->OptionalResponse[0])
|
||||
{
|
||||
$sResult = $oResponse->HumanReadable;
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8469
rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
Normal file
8469
rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
Normal file
File diff suppressed because it is too large
Load diff
224
rainloop/v/0.0.0/app/libraries/RainLoop/Api.php
Normal file
224
rainloop/v/0.0.0/app/libraries/RainLoop/Api.php
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Api
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function RunResult()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @staticvar bool $bOne
|
||||
* @return bool
|
||||
*/
|
||||
public static function Handle()
|
||||
{
|
||||
static $bOne = null;
|
||||
if (null === $bOne)
|
||||
{
|
||||
$bOne = \class_exists('MailSo\Version');
|
||||
if ($bOne)
|
||||
{
|
||||
\RainLoop\Api::SetupDefaultMailSoConfig();
|
||||
$bOne = \RainLoop\Api::RunResult();
|
||||
}
|
||||
}
|
||||
|
||||
return $bOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Actions
|
||||
*/
|
||||
public static function Actions()
|
||||
{
|
||||
static $oActions = null;
|
||||
if (null === $oActions)
|
||||
{
|
||||
$oActions = \RainLoop\Actions::NewInstance();
|
||||
}
|
||||
|
||||
return $oActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Application
|
||||
*/
|
||||
public static function Config()
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Config();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \MailSo\Log\Logger
|
||||
*/
|
||||
public static function Logger()
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Logger();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function SetupDefaultMailSoConfig()
|
||||
{
|
||||
if (\class_exists('MailSo\Config'))
|
||||
{
|
||||
if (\RainLoop\Api::Config()->Get('labs', 'disable_iconv_if_mbstring_supported', false) &&
|
||||
\MailSo\Base\Utils::IsMbStringSupported() && \MailSo\Config::$MBSTRING)
|
||||
{
|
||||
\MailSo\Config::$ICONV = false;
|
||||
}
|
||||
|
||||
\MailSo\Config::$MessageListFastSimpleSearch =
|
||||
!!\RainLoop\Api::Config()->Get('labs', 'imap_message_list_fast_simple_search', true);
|
||||
|
||||
\MailSo\Config::$MessageListCountLimitTrigger =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_count_limit_trigger', 0);
|
||||
|
||||
\MailSo\Config::$MessageListDateFilter =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_date_filter', 0);
|
||||
|
||||
\MailSo\Config::$LargeThreadLimit =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_large_thread_limit', 100);
|
||||
|
||||
\MailSo\Config::$SystemLogger = \RainLoop\Api::Logger();
|
||||
|
||||
$sSslCafile = \RainLoop\Api::Config()->Get('ssl', 'cafile', '');
|
||||
$sSslCapath = \RainLoop\Api::Config()->Get('ssl', 'capath', '');
|
||||
|
||||
if (!empty($sSslCafile) || !empty($sSslCapath))
|
||||
{
|
||||
\MailSo\Hooks::Add('Net.NetClient.StreamContextSettings/Filter', function (&$aStreamContextSettings) use ($sSslCafile, $sSslCapath) {
|
||||
if (isset($aStreamContextSettings['ssl']) && \is_array($aStreamContextSettings['ssl']))
|
||||
{
|
||||
if (empty($aStreamContextSettings['ssl']['cafile']) && !empty($sSslCafile))
|
||||
{
|
||||
$aStreamContextSettings['ssl']['cafile'] = $sSslCafile;
|
||||
}
|
||||
|
||||
if (empty($aStreamContextSettings['ssl']['capath']) && !empty($sSslCapath))
|
||||
{
|
||||
$aStreamContextSettings['ssl']['capath'] = $sSslCapath;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function Version()
|
||||
{
|
||||
return APP_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sPassword
|
||||
* @param bool $bUseTimeout = true
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function GetUserSsoHash($sEmail, $sPassword, $bUseTimeout = true)
|
||||
{
|
||||
$sSsoHash = \sha1(\rand(10000, 99999).$sEmail.$sPassword.\microtime(true));
|
||||
|
||||
return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash), \RainLoop\Utils::EncodeKeyValues(array(
|
||||
'Email' => $sEmail,
|
||||
'Password' => $sPassword,
|
||||
'Time' => $bUseTimeout ? \time() : 0
|
||||
))) ? $sSsoHash : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSsoHash
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ClearUserSsoHash($sSsoHash)
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Cacher()->Delete(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ClearUserData($sEmail)
|
||||
{
|
||||
if (0 < \strlen($sEmail))
|
||||
{
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail);
|
||||
|
||||
$oStorageProvider = \RainLoop\Api::Actions()->StorageProvider();
|
||||
if ($oStorageProvider && $oStorageProvider->IsActive())
|
||||
{
|
||||
// TwoFactor Auth User Data
|
||||
$oStorageProvider->Clear(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
\RainLoop\KeyPathHelper::TwoFactorAuthUserData($sEmail)
|
||||
);
|
||||
|
||||
// Accounts list
|
||||
$oStorageProvider->Clear(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
\RainLoop\KeyPathHelper::WebmailAccounts($sEmail)
|
||||
);
|
||||
|
||||
// Contact sync data
|
||||
$oStorageProvider->Clear($sEmail,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||
'contacts_sync'
|
||||
);
|
||||
}
|
||||
|
||||
\RainLoop\Api::Actions()->SettingsProvider()->ClearByEmail($sEmail);
|
||||
|
||||
if (\RainLoop\Api::Actions()->AddressBookProvider() &&
|
||||
\RainLoop\Api::Actions()->AddressBookProvider()->IsActive())
|
||||
{
|
||||
\RainLoop\Api::Actions()->AddressBookProvider()->DeleteAllContacts($sEmail);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function LogoutCurrentLogginedUser()
|
||||
{
|
||||
\RainLoop\Utils::ClearCookie('rlsession');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function ExitOnEnd()
|
||||
{
|
||||
if (!\defined('RAINLOOP_EXIT_ON_END'))
|
||||
{
|
||||
\define('RAINLOOP_EXIT_ON_END', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Account {}
|
||||
464
rainloop/v/0.0.0/app/libraries/RainLoop/Common/MbStringFix.php
Normal file
464
rainloop/v/0.0.0/app/libraries/RainLoop/Common/MbStringFix.php
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
<?php
|
||||
|
||||
if (!function_exists('mb_strtoupper'))
|
||||
{
|
||||
function mb_strtoupper($s, $encoding = INF)
|
||||
{
|
||||
if ('' === $s .= '') return '';
|
||||
|
||||
if (INF === $encoding) $encoding = 'UTF-8';
|
||||
else $encoding = strtoupper($encoding);
|
||||
|
||||
if ('UTF-8' === $encoding || 'UTF8' === $encoding) $encoding = INF;
|
||||
else $s = function_exists('iconv') ? iconv($encoding, 'UTF-8//IGNORE', $s) : $s;
|
||||
|
||||
static $upper;
|
||||
isset($upper) || $upper = unserialize(base64_decode('YToxMDUxOntzOjE6ImEiO3M6MToiQSI7czoxOiJiIjtzOjE6IkIiO3M6MToiYyI7czoxOiJDIjtz
|
||||
OjE6ImQiO3M6MToiRCI7czoxOiJlIjtzOjE6IkUiO3M6MToiZiI7czoxOiJGIjtzOjE6ImciO3M6
|
||||
MToiRyI7czoxOiJoIjtzOjE6IkgiO3M6MToiaSI7czoxOiJJIjtzOjE6ImoiO3M6MToiSiI7czox
|
||||
OiJrIjtzOjE6IksiO3M6MToibCI7czoxOiJMIjtzOjE6Im0iO3M6MToiTSI7czoxOiJuIjtzOjE6
|
||||
Ik4iO3M6MToibyI7czoxOiJPIjtzOjE6InAiO3M6MToiUCI7czoxOiJxIjtzOjE6IlEiO3M6MToi
|
||||
ciI7czoxOiJSIjtzOjE6InMiO3M6MToiUyI7czoxOiJ0IjtzOjE6IlQiO3M6MToidSI7czoxOiJV
|
||||
IjtzOjE6InYiO3M6MToiViI7czoxOiJ3IjtzOjE6IlciO3M6MToieCI7czoxOiJYIjtzOjE6Inki
|
||||
O3M6MToiWSI7czoxOiJ6IjtzOjE6IloiO3M6MjoiwrUiO3M6MjoizpwiO3M6Mjoiw6AiO3M6Mjoi
|
||||
w4AiO3M6Mjoiw6EiO3M6Mjoiw4EiO3M6Mjoiw6IiO3M6Mjoiw4IiO3M6Mjoiw6MiO3M6Mjoiw4Mi
|
||||
O3M6Mjoiw6QiO3M6Mjoiw4QiO3M6Mjoiw6UiO3M6Mjoiw4UiO3M6Mjoiw6YiO3M6Mjoiw4YiO3M6
|
||||
Mjoiw6ciO3M6Mjoiw4ciO3M6Mjoiw6giO3M6Mjoiw4giO3M6Mjoiw6kiO3M6Mjoiw4kiO3M6Mjoi
|
||||
w6oiO3M6Mjoiw4oiO3M6Mjoiw6siO3M6Mjoiw4siO3M6Mjoiw6wiO3M6Mjoiw4wiO3M6Mjoiw60i
|
||||
O3M6Mjoiw40iO3M6Mjoiw64iO3M6Mjoiw44iO3M6Mjoiw68iO3M6Mjoiw48iO3M6Mjoiw7AiO3M6
|
||||
Mjoiw5AiO3M6Mjoiw7EiO3M6Mjoiw5EiO3M6Mjoiw7IiO3M6Mjoiw5IiO3M6Mjoiw7MiO3M6Mjoi
|
||||
w5MiO3M6Mjoiw7QiO3M6Mjoiw5QiO3M6Mjoiw7UiO3M6Mjoiw5UiO3M6Mjoiw7YiO3M6Mjoiw5Yi
|
||||
O3M6Mjoiw7giO3M6Mjoiw5giO3M6Mjoiw7kiO3M6Mjoiw5kiO3M6Mjoiw7oiO3M6Mjoiw5oiO3M6
|
||||
Mjoiw7siO3M6Mjoiw5siO3M6Mjoiw7wiO3M6Mjoiw5wiO3M6Mjoiw70iO3M6Mjoiw50iO3M6Mjoi
|
||||
w74iO3M6Mjoiw54iO3M6Mjoiw78iO3M6MjoixbgiO3M6MjoixIEiO3M6MjoixIAiO3M6MjoixIMi
|
||||
O3M6MjoixIIiO3M6MjoixIUiO3M6MjoixIQiO3M6MjoixIciO3M6MjoixIYiO3M6MjoixIkiO3M6
|
||||
MjoixIgiO3M6MjoixIsiO3M6MjoixIoiO3M6MjoixI0iO3M6MjoixIwiO3M6MjoixI8iO3M6Mjoi
|
||||
xI4iO3M6MjoixJEiO3M6MjoixJAiO3M6MjoixJMiO3M6MjoixJIiO3M6MjoixJUiO3M6MjoixJQi
|
||||
O3M6MjoixJciO3M6MjoixJYiO3M6MjoixJkiO3M6MjoixJgiO3M6MjoixJsiO3M6MjoixJoiO3M6
|
||||
MjoixJ0iO3M6MjoixJwiO3M6MjoixJ8iO3M6MjoixJ4iO3M6MjoixKEiO3M6MjoixKAiO3M6Mjoi
|
||||
xKMiO3M6MjoixKIiO3M6MjoixKUiO3M6MjoixKQiO3M6MjoixKciO3M6MjoixKYiO3M6MjoixKki
|
||||
O3M6MjoixKgiO3M6MjoixKsiO3M6MjoixKoiO3M6MjoixK0iO3M6MjoixKwiO3M6MjoixK8iO3M6
|
||||
MjoixK4iO3M6MjoixLEiO3M6MToiSSI7czoyOiLEsyI7czoyOiLEsiI7czoyOiLEtSI7czoyOiLE
|
||||
tCI7czoyOiLEtyI7czoyOiLEtiI7czoyOiLEuiI7czoyOiLEuSI7czoyOiLEvCI7czoyOiLEuyI7
|
||||
czoyOiLEviI7czoyOiLEvSI7czoyOiLFgCI7czoyOiLEvyI7czoyOiLFgiI7czoyOiLFgSI7czoy
|
||||
OiLFhCI7czoyOiLFgyI7czoyOiLFhiI7czoyOiLFhSI7czoyOiLFiCI7czoyOiLFhyI7czoyOiLF
|
||||
iyI7czoyOiLFiiI7czoyOiLFjSI7czoyOiLFjCI7czoyOiLFjyI7czoyOiLFjiI7czoyOiLFkSI7
|
||||
czoyOiLFkCI7czoyOiLFkyI7czoyOiLFkiI7czoyOiLFlSI7czoyOiLFlCI7czoyOiLFlyI7czoy
|
||||
OiLFliI7czoyOiLFmSI7czoyOiLFmCI7czoyOiLFmyI7czoyOiLFmiI7czoyOiLFnSI7czoyOiLF
|
||||
nCI7czoyOiLFnyI7czoyOiLFniI7czoyOiLFoSI7czoyOiLFoCI7czoyOiLFoyI7czoyOiLFoiI7
|
||||
czoyOiLFpSI7czoyOiLFpCI7czoyOiLFpyI7czoyOiLFpiI7czoyOiLFqSI7czoyOiLFqCI7czoy
|
||||
OiLFqyI7czoyOiLFqiI7czoyOiLFrSI7czoyOiLFrCI7czoyOiLFryI7czoyOiLFriI7czoyOiLF
|
||||
sSI7czoyOiLFsCI7czoyOiLFsyI7czoyOiLFsiI7czoyOiLFtSI7czoyOiLFtCI7czoyOiLFtyI7
|
||||
czoyOiLFtiI7czoyOiLFuiI7czoyOiLFuSI7czoyOiLFvCI7czoyOiLFuyI7czoyOiLFviI7czoy
|
||||
OiLFvSI7czoyOiLFvyI7czoxOiJTIjtzOjI6IsaAIjtzOjI6IsmDIjtzOjI6IsaDIjtzOjI6IsaC
|
||||
IjtzOjI6IsaFIjtzOjI6IsaEIjtzOjI6IsaIIjtzOjI6IsaHIjtzOjI6IsaMIjtzOjI6IsaLIjtz
|
||||
OjI6IsaSIjtzOjI6IsaRIjtzOjI6IsaVIjtzOjI6Ise2IjtzOjI6IsaZIjtzOjI6IsaYIjtzOjI6
|
||||
IsaaIjtzOjI6Isi9IjtzOjI6IsaeIjtzOjI6IsigIjtzOjI6IsahIjtzOjI6IsagIjtzOjI6Isaj
|
||||
IjtzOjI6IsaiIjtzOjI6IsalIjtzOjI6IsakIjtzOjI6IsaoIjtzOjI6IsanIjtzOjI6IsatIjtz
|
||||
OjI6IsasIjtzOjI6IsawIjtzOjI6IsavIjtzOjI6Isa0IjtzOjI6IsazIjtzOjI6Isa2IjtzOjI6
|
||||
Isa1IjtzOjI6Isa5IjtzOjI6Isa4IjtzOjI6Isa9IjtzOjI6Isa8IjtzOjI6Isa/IjtzOjI6Ise3
|
||||
IjtzOjI6IseFIjtzOjI6IseEIjtzOjI6IseGIjtzOjI6IseEIjtzOjI6IseIIjtzOjI6IseHIjtz
|
||||
OjI6IseJIjtzOjI6IseHIjtzOjI6IseLIjtzOjI6IseKIjtzOjI6IseMIjtzOjI6IseKIjtzOjI6
|
||||
IseOIjtzOjI6IseNIjtzOjI6IseQIjtzOjI6IsePIjtzOjI6IseSIjtzOjI6IseRIjtzOjI6IseU
|
||||
IjtzOjI6IseTIjtzOjI6IseWIjtzOjI6IseVIjtzOjI6IseYIjtzOjI6IseXIjtzOjI6IseaIjtz
|
||||
OjI6IseZIjtzOjI6IsecIjtzOjI6IsebIjtzOjI6IsedIjtzOjI6IsaOIjtzOjI6IsefIjtzOjI6
|
||||
IseeIjtzOjI6IsehIjtzOjI6IsegIjtzOjI6IsejIjtzOjI6IseiIjtzOjI6IselIjtzOjI6Isek
|
||||
IjtzOjI6IsenIjtzOjI6IsemIjtzOjI6IsepIjtzOjI6IseoIjtzOjI6IserIjtzOjI6IseqIjtz
|
||||
OjI6IsetIjtzOjI6IsesIjtzOjI6IsevIjtzOjI6IseuIjtzOjI6IseyIjtzOjI6IsexIjtzOjI6
|
||||
IsezIjtzOjI6IsexIjtzOjI6Ise1IjtzOjI6Ise0IjtzOjI6Ise5IjtzOjI6Ise4IjtzOjI6Ise7
|
||||
IjtzOjI6Ise6IjtzOjI6Ise9IjtzOjI6Ise8IjtzOjI6Ise/IjtzOjI6Ise+IjtzOjI6IsiBIjtz
|
||||
OjI6IsiAIjtzOjI6IsiDIjtzOjI6IsiCIjtzOjI6IsiFIjtzOjI6IsiEIjtzOjI6IsiHIjtzOjI6
|
||||
IsiGIjtzOjI6IsiJIjtzOjI6IsiIIjtzOjI6IsiLIjtzOjI6IsiKIjtzOjI6IsiNIjtzOjI6IsiM
|
||||
IjtzOjI6IsiPIjtzOjI6IsiOIjtzOjI6IsiRIjtzOjI6IsiQIjtzOjI6IsiTIjtzOjI6IsiSIjtz
|
||||
OjI6IsiVIjtzOjI6IsiUIjtzOjI6IsiXIjtzOjI6IsiWIjtzOjI6IsiZIjtzOjI6IsiYIjtzOjI6
|
||||
IsibIjtzOjI6IsiaIjtzOjI6IsidIjtzOjI6IsicIjtzOjI6IsifIjtzOjI6IsieIjtzOjI6Isij
|
||||
IjtzOjI6IsiiIjtzOjI6IsilIjtzOjI6IsikIjtzOjI6IsinIjtzOjI6IsimIjtzOjI6IsipIjtz
|
||||
OjI6IsioIjtzOjI6IsirIjtzOjI6IsiqIjtzOjI6IsitIjtzOjI6IsisIjtzOjI6IsivIjtzOjI6
|
||||
IsiuIjtzOjI6IsixIjtzOjI6IsiwIjtzOjI6IsizIjtzOjI6IsiyIjtzOjI6Isi8IjtzOjI6Isi7
|
||||
IjtzOjI6Isi/IjtzOjM6IuKxviI7czoyOiLJgCI7czozOiLisb8iO3M6MjoiyYIiO3M6MjoiyYEi
|
||||
O3M6MjoiyYciO3M6MjoiyYYiO3M6MjoiyYkiO3M6MjoiyYgiO3M6MjoiyYsiO3M6MjoiyYoiO3M6
|
||||
MjoiyY0iO3M6MjoiyYwiO3M6MjoiyY8iO3M6MjoiyY4iO3M6MjoiyZAiO3M6Mzoi4rGvIjtzOjI6
|
||||
IsmRIjtzOjM6IuKxrSI7czoyOiLJkiI7czozOiLisbAiO3M6MjoiyZMiO3M6MjoixoEiO3M6Mjoi
|
||||
yZQiO3M6MjoixoYiO3M6MjoiyZYiO3M6MjoixokiO3M6MjoiyZciO3M6MjoixooiO3M6MjoiyZki
|
||||
O3M6Mjoixo8iO3M6MjoiyZsiO3M6MjoixpAiO3M6MjoiyaAiO3M6MjoixpMiO3M6MjoiyaMiO3M6
|
||||
MjoixpQiO3M6MjoiyaUiO3M6Mzoi6p6NIjtzOjI6IsmmIjtzOjM6IuqeqiI7czoyOiLJqCI7czoy
|
||||
OiLGlyI7czoyOiLJqSI7czoyOiLGliI7czoyOiLJqyI7czozOiLisaIiO3M6Mjoiya8iO3M6Mjoi
|
||||
xpwiO3M6MjoiybEiO3M6Mzoi4rGuIjtzOjI6IsmyIjtzOjI6IsadIjtzOjI6Ism1IjtzOjI6Isaf
|
||||
IjtzOjI6Ism9IjtzOjM6IuKxpCI7czoyOiLKgCI7czoyOiLGpiI7czoyOiLKgyI7czoyOiLGqSI7
|
||||
czoyOiLKiCI7czoyOiLGriI7czoyOiLKiSI7czoyOiLJhCI7czoyOiLKiiI7czoyOiLGsSI7czoy
|
||||
OiLKiyI7czoyOiLGsiI7czoyOiLKjCI7czoyOiLJhSI7czoyOiLKkiI7czoyOiLGtyI7czoyOiLN
|
||||
hSI7czoyOiLOmSI7czoyOiLNsSI7czoyOiLNsCI7czoyOiLNsyI7czoyOiLNsiI7czoyOiLNtyI7
|
||||
czoyOiLNtiI7czoyOiLNuyI7czoyOiLPvSI7czoyOiLNvCI7czoyOiLPviI7czoyOiLNvSI7czoy
|
||||
OiLPvyI7czoyOiLOrCI7czoyOiLOhiI7czoyOiLOrSI7czoyOiLOiCI7czoyOiLOriI7czoyOiLO
|
||||
iSI7czoyOiLOryI7czoyOiLOiiI7czoyOiLOsSI7czoyOiLOkSI7czoyOiLOsiI7czoyOiLOkiI7
|
||||
czoyOiLOsyI7czoyOiLOkyI7czoyOiLOtCI7czoyOiLOlCI7czoyOiLOtSI7czoyOiLOlSI7czoy
|
||||
OiLOtiI7czoyOiLOliI7czoyOiLOtyI7czoyOiLOlyI7czoyOiLOuCI7czoyOiLOmCI7czoyOiLO
|
||||
uSI7czoyOiLOmSI7czoyOiLOuiI7czoyOiLOmiI7czoyOiLOuyI7czoyOiLOmyI7czoyOiLOvCI7
|
||||
czoyOiLOnCI7czoyOiLOvSI7czoyOiLOnSI7czoyOiLOviI7czoyOiLOniI7czoyOiLOvyI7czoy
|
||||
OiLOnyI7czoyOiLPgCI7czoyOiLOoCI7czoyOiLPgSI7czoyOiLOoSI7czoyOiLPgiI7czoyOiLO
|
||||
oyI7czoyOiLPgyI7czoyOiLOoyI7czoyOiLPhCI7czoyOiLOpCI7czoyOiLPhSI7czoyOiLOpSI7
|
||||
czoyOiLPhiI7czoyOiLOpiI7czoyOiLPhyI7czoyOiLOpyI7czoyOiLPiCI7czoyOiLOqCI7czoy
|
||||
OiLPiSI7czoyOiLOqSI7czoyOiLPiiI7czoyOiLOqiI7czoyOiLPiyI7czoyOiLOqyI7czoyOiLP
|
||||
jCI7czoyOiLOjCI7czoyOiLPjSI7czoyOiLOjiI7czoyOiLPjiI7czoyOiLOjyI7czoyOiLPkCI7
|
||||
czoyOiLOkiI7czoyOiLPkSI7czoyOiLOmCI7czoyOiLPlSI7czoyOiLOpiI7czoyOiLPliI7czoy
|
||||
OiLOoCI7czoyOiLPlyI7czoyOiLPjyI7czoyOiLPmSI7czoyOiLPmCI7czoyOiLPmyI7czoyOiLP
|
||||
miI7czoyOiLPnSI7czoyOiLPnCI7czoyOiLPnyI7czoyOiLPniI7czoyOiLPoSI7czoyOiLPoCI7
|
||||
czoyOiLPoyI7czoyOiLPoiI7czoyOiLPpSI7czoyOiLPpCI7czoyOiLPpyI7czoyOiLPpiI7czoy
|
||||
OiLPqSI7czoyOiLPqCI7czoyOiLPqyI7czoyOiLPqiI7czoyOiLPrSI7czoyOiLPrCI7czoyOiLP
|
||||
ryI7czoyOiLPriI7czoyOiLPsCI7czoyOiLOmiI7czoyOiLPsSI7czoyOiLOoSI7czoyOiLPsiI7
|
||||
czoyOiLPuSI7czoyOiLPtSI7czoyOiLOlSI7czoyOiLPuCI7czoyOiLPtyI7czoyOiLPuyI7czoy
|
||||
OiLPuiI7czoyOiLQsCI7czoyOiLQkCI7czoyOiLQsSI7czoyOiLQkSI7czoyOiLQsiI7czoyOiLQ
|
||||
kiI7czoyOiLQsyI7czoyOiLQkyI7czoyOiLQtCI7czoyOiLQlCI7czoyOiLQtSI7czoyOiLQlSI7
|
||||
czoyOiLQtiI7czoyOiLQliI7czoyOiLQtyI7czoyOiLQlyI7czoyOiLQuCI7czoyOiLQmCI7czoy
|
||||
OiLQuSI7czoyOiLQmSI7czoyOiLQuiI7czoyOiLQmiI7czoyOiLQuyI7czoyOiLQmyI7czoyOiLQ
|
||||
vCI7czoyOiLQnCI7czoyOiLQvSI7czoyOiLQnSI7czoyOiLQviI7czoyOiLQniI7czoyOiLQvyI7
|
||||
czoyOiLQnyI7czoyOiLRgCI7czoyOiLQoCI7czoyOiLRgSI7czoyOiLQoSI7czoyOiLRgiI7czoy
|
||||
OiLQoiI7czoyOiLRgyI7czoyOiLQoyI7czoyOiLRhCI7czoyOiLQpCI7czoyOiLRhSI7czoyOiLQ
|
||||
pSI7czoyOiLRhiI7czoyOiLQpiI7czoyOiLRhyI7czoyOiLQpyI7czoyOiLRiCI7czoyOiLQqCI7
|
||||
czoyOiLRiSI7czoyOiLQqSI7czoyOiLRiiI7czoyOiLQqiI7czoyOiLRiyI7czoyOiLQqyI7czoy
|
||||
OiLRjCI7czoyOiLQrCI7czoyOiLRjSI7czoyOiLQrSI7czoyOiLRjiI7czoyOiLQriI7czoyOiLR
|
||||
jyI7czoyOiLQryI7czoyOiLRkCI7czoyOiLQgCI7czoyOiLRkSI7czoyOiLQgSI7czoyOiLRkiI7
|
||||
czoyOiLQgiI7czoyOiLRkyI7czoyOiLQgyI7czoyOiLRlCI7czoyOiLQhCI7czoyOiLRlSI7czoy
|
||||
OiLQhSI7czoyOiLRliI7czoyOiLQhiI7czoyOiLRlyI7czoyOiLQhyI7czoyOiLRmCI7czoyOiLQ
|
||||
iCI7czoyOiLRmSI7czoyOiLQiSI7czoyOiLRmiI7czoyOiLQiiI7czoyOiLRmyI7czoyOiLQiyI7
|
||||
czoyOiLRnCI7czoyOiLQjCI7czoyOiLRnSI7czoyOiLQjSI7czoyOiLRniI7czoyOiLQjiI7czoy
|
||||
OiLRnyI7czoyOiLQjyI7czoyOiLRoSI7czoyOiLRoCI7czoyOiLRoyI7czoyOiLRoiI7czoyOiLR
|
||||
pSI7czoyOiLRpCI7czoyOiLRpyI7czoyOiLRpiI7czoyOiLRqSI7czoyOiLRqCI7czoyOiLRqyI7
|
||||
czoyOiLRqiI7czoyOiLRrSI7czoyOiLRrCI7czoyOiLRryI7czoyOiLRriI7czoyOiLRsSI7czoy
|
||||
OiLRsCI7czoyOiLRsyI7czoyOiLRsiI7czoyOiLRtSI7czoyOiLRtCI7czoyOiLRtyI7czoyOiLR
|
||||
tiI7czoyOiLRuSI7czoyOiLRuCI7czoyOiLRuyI7czoyOiLRuiI7czoyOiLRvSI7czoyOiLRvCI7
|
||||
czoyOiLRvyI7czoyOiLRviI7czoyOiLSgSI7czoyOiLSgCI7czoyOiLSiyI7czoyOiLSiiI7czoy
|
||||
OiLSjSI7czoyOiLSjCI7czoyOiLSjyI7czoyOiLSjiI7czoyOiLSkSI7czoyOiLSkCI7czoyOiLS
|
||||
kyI7czoyOiLSkiI7czoyOiLSlSI7czoyOiLSlCI7czoyOiLSlyI7czoyOiLSliI7czoyOiLSmSI7
|
||||
czoyOiLSmCI7czoyOiLSmyI7czoyOiLSmiI7czoyOiLSnSI7czoyOiLSnCI7czoyOiLSnyI7czoy
|
||||
OiLSniI7czoyOiLSoSI7czoyOiLSoCI7czoyOiLSoyI7czoyOiLSoiI7czoyOiLSpSI7czoyOiLS
|
||||
pCI7czoyOiLSpyI7czoyOiLSpiI7czoyOiLSqSI7czoyOiLSqCI7czoyOiLSqyI7czoyOiLSqiI7
|
||||
czoyOiLSrSI7czoyOiLSrCI7czoyOiLSryI7czoyOiLSriI7czoyOiLSsSI7czoyOiLSsCI7czoy
|
||||
OiLSsyI7czoyOiLSsiI7czoyOiLStSI7czoyOiLStCI7czoyOiLStyI7czoyOiLStiI7czoyOiLS
|
||||
uSI7czoyOiLSuCI7czoyOiLSuyI7czoyOiLSuiI7czoyOiLSvSI7czoyOiLSvCI7czoyOiLSvyI7
|
||||
czoyOiLSviI7czoyOiLTgiI7czoyOiLTgSI7czoyOiLThCI7czoyOiLTgyI7czoyOiLThiI7czoy
|
||||
OiLThSI7czoyOiLTiCI7czoyOiLThyI7czoyOiLTiiI7czoyOiLTiSI7czoyOiLTjCI7czoyOiLT
|
||||
iyI7czoyOiLTjiI7czoyOiLTjSI7czoyOiLTjyI7czoyOiLTgCI7czoyOiLTkSI7czoyOiLTkCI7
|
||||
czoyOiLTkyI7czoyOiLTkiI7czoyOiLTlSI7czoyOiLTlCI7czoyOiLTlyI7czoyOiLTliI7czoy
|
||||
OiLTmSI7czoyOiLTmCI7czoyOiLTmyI7czoyOiLTmiI7czoyOiLTnSI7czoyOiLTnCI7czoyOiLT
|
||||
nyI7czoyOiLTniI7czoyOiLToSI7czoyOiLToCI7czoyOiLToyI7czoyOiLToiI7czoyOiLTpSI7
|
||||
czoyOiLTpCI7czoyOiLTpyI7czoyOiLTpiI7czoyOiLTqSI7czoyOiLTqCI7czoyOiLTqyI7czoy
|
||||
OiLTqiI7czoyOiLTrSI7czoyOiLTrCI7czoyOiLTryI7czoyOiLTriI7czoyOiLTsSI7czoyOiLT
|
||||
sCI7czoyOiLTsyI7czoyOiLTsiI7czoyOiLTtSI7czoyOiLTtCI7czoyOiLTtyI7czoyOiLTtiI7
|
||||
czoyOiLTuSI7czoyOiLTuCI7czoyOiLTuyI7czoyOiLTuiI7czoyOiLTvSI7czoyOiLTvCI7czoy
|
||||
OiLTvyI7czoyOiLTviI7czoyOiLUgSI7czoyOiLUgCI7czoyOiLUgyI7czoyOiLUgiI7czoyOiLU
|
||||
hSI7czoyOiLUhCI7czoyOiLUhyI7czoyOiLUhiI7czoyOiLUiSI7czoyOiLUiCI7czoyOiLUiyI7
|
||||
czoyOiLUiiI7czoyOiLUjSI7czoyOiLUjCI7czoyOiLUjyI7czoyOiLUjiI7czoyOiLUkSI7czoy
|
||||
OiLUkCI7czoyOiLUkyI7czoyOiLUkiI7czoyOiLUlSI7czoyOiLUlCI7czoyOiLUlyI7czoyOiLU
|
||||
liI7czoyOiLUmSI7czoyOiLUmCI7czoyOiLUmyI7czoyOiLUmiI7czoyOiLUnSI7czoyOiLUnCI7
|
||||
czoyOiLUnyI7czoyOiLUniI7czoyOiLUoSI7czoyOiLUoCI7czoyOiLUoyI7czoyOiLUoiI7czoy
|
||||
OiLUpSI7czoyOiLUpCI7czoyOiLUpyI7czoyOiLUpiI7czoyOiLVoSI7czoyOiLUsSI7czoyOiLV
|
||||
oiI7czoyOiLUsiI7czoyOiLVoyI7czoyOiLUsyI7czoyOiLVpCI7czoyOiLUtCI7czoyOiLVpSI7
|
||||
czoyOiLUtSI7czoyOiLVpiI7czoyOiLUtiI7czoyOiLVpyI7czoyOiLUtyI7czoyOiLVqCI7czoy
|
||||
OiLUuCI7czoyOiLVqSI7czoyOiLUuSI7czoyOiLVqiI7czoyOiLUuiI7czoyOiLVqyI7czoyOiLU
|
||||
uyI7czoyOiLVrCI7czoyOiLUvCI7czoyOiLVrSI7czoyOiLUvSI7czoyOiLVriI7czoyOiLUviI7
|
||||
czoyOiLVryI7czoyOiLUvyI7czoyOiLVsCI7czoyOiLVgCI7czoyOiLVsSI7czoyOiLVgSI7czoy
|
||||
OiLVsiI7czoyOiLVgiI7czoyOiLVsyI7czoyOiLVgyI7czoyOiLVtCI7czoyOiLVhCI7czoyOiLV
|
||||
tSI7czoyOiLVhSI7czoyOiLVtiI7czoyOiLVhiI7czoyOiLVtyI7czoyOiLVhyI7czoyOiLVuCI7
|
||||
czoyOiLViCI7czoyOiLVuSI7czoyOiLViSI7czoyOiLVuiI7czoyOiLViiI7czoyOiLVuyI7czoy
|
||||
OiLViyI7czoyOiLVvCI7czoyOiLVjCI7czoyOiLVvSI7czoyOiLVjSI7czoyOiLVviI7czoyOiLV
|
||||
jiI7czoyOiLVvyI7czoyOiLVjyI7czoyOiLWgCI7czoyOiLVkCI7czoyOiLWgSI7czoyOiLVkSI7
|
||||
czoyOiLWgiI7czoyOiLVkiI7czoyOiLWgyI7czoyOiLVkyI7czoyOiLWhCI7czoyOiLVlCI7czoy
|
||||
OiLWhSI7czoyOiLVlSI7czoyOiLWhiI7czoyOiLVliI7czozOiLhtbkiO3M6Mzoi6p29IjtzOjM6
|
||||
IuG1vSI7czozOiLisaMiO3M6Mzoi4biBIjtzOjM6IuG4gCI7czozOiLhuIMiO3M6Mzoi4biCIjtz
|
||||
OjM6IuG4hSI7czozOiLhuIQiO3M6Mzoi4biHIjtzOjM6IuG4hiI7czozOiLhuIkiO3M6Mzoi4biI
|
||||
IjtzOjM6IuG4iyI7czozOiLhuIoiO3M6Mzoi4biNIjtzOjM6IuG4jCI7czozOiLhuI8iO3M6Mzoi
|
||||
4biOIjtzOjM6IuG4kSI7czozOiLhuJAiO3M6Mzoi4biTIjtzOjM6IuG4kiI7czozOiLhuJUiO3M6
|
||||
Mzoi4biUIjtzOjM6IuG4lyI7czozOiLhuJYiO3M6Mzoi4biZIjtzOjM6IuG4mCI7czozOiLhuJsi
|
||||
O3M6Mzoi4biaIjtzOjM6IuG4nSI7czozOiLhuJwiO3M6Mzoi4bifIjtzOjM6IuG4niI7czozOiLh
|
||||
uKEiO3M6Mzoi4bigIjtzOjM6IuG4oyI7czozOiLhuKIiO3M6Mzoi4bilIjtzOjM6IuG4pCI7czoz
|
||||
OiLhuKciO3M6Mzoi4bimIjtzOjM6IuG4qSI7czozOiLhuKgiO3M6Mzoi4birIjtzOjM6IuG4qiI7
|
||||
czozOiLhuK0iO3M6Mzoi4bisIjtzOjM6IuG4ryI7czozOiLhuK4iO3M6Mzoi4bixIjtzOjM6IuG4
|
||||
sCI7czozOiLhuLMiO3M6Mzoi4biyIjtzOjM6IuG4tSI7czozOiLhuLQiO3M6Mzoi4bi3IjtzOjM6
|
||||
IuG4tiI7czozOiLhuLkiO3M6Mzoi4bi4IjtzOjM6IuG4uyI7czozOiLhuLoiO3M6Mzoi4bi9Ijtz
|
||||
OjM6IuG4vCI7czozOiLhuL8iO3M6Mzoi4bi+IjtzOjM6IuG5gSI7czozOiLhuYAiO3M6Mzoi4bmD
|
||||
IjtzOjM6IuG5giI7czozOiLhuYUiO3M6Mzoi4bmEIjtzOjM6IuG5hyI7czozOiLhuYYiO3M6Mzoi
|
||||
4bmJIjtzOjM6IuG5iCI7czozOiLhuYsiO3M6Mzoi4bmKIjtzOjM6IuG5jSI7czozOiLhuYwiO3M6
|
||||
Mzoi4bmPIjtzOjM6IuG5jiI7czozOiLhuZEiO3M6Mzoi4bmQIjtzOjM6IuG5kyI7czozOiLhuZIi
|
||||
O3M6Mzoi4bmVIjtzOjM6IuG5lCI7czozOiLhuZciO3M6Mzoi4bmWIjtzOjM6IuG5mSI7czozOiLh
|
||||
uZgiO3M6Mzoi4bmbIjtzOjM6IuG5miI7czozOiLhuZ0iO3M6Mzoi4bmcIjtzOjM6IuG5nyI7czoz
|
||||
OiLhuZ4iO3M6Mzoi4bmhIjtzOjM6IuG5oCI7czozOiLhuaMiO3M6Mzoi4bmiIjtzOjM6IuG5pSI7
|
||||
czozOiLhuaQiO3M6Mzoi4bmnIjtzOjM6IuG5piI7czozOiLhuakiO3M6Mzoi4bmoIjtzOjM6IuG5
|
||||
qyI7czozOiLhuaoiO3M6Mzoi4bmtIjtzOjM6IuG5rCI7czozOiLhua8iO3M6Mzoi4bmuIjtzOjM6
|
||||
IuG5sSI7czozOiLhubAiO3M6Mzoi4bmzIjtzOjM6IuG5siI7czozOiLhubUiO3M6Mzoi4bm0Ijtz
|
||||
OjM6IuG5tyI7czozOiLhubYiO3M6Mzoi4bm5IjtzOjM6IuG5uCI7czozOiLhubsiO3M6Mzoi4bm6
|
||||
IjtzOjM6IuG5vSI7czozOiLhubwiO3M6Mzoi4bm/IjtzOjM6IuG5viI7czozOiLhuoEiO3M6Mzoi
|
||||
4bqAIjtzOjM6IuG6gyI7czozOiLhuoIiO3M6Mzoi4bqFIjtzOjM6IuG6hCI7czozOiLhuociO3M6
|
||||
Mzoi4bqGIjtzOjM6IuG6iSI7czozOiLhuogiO3M6Mzoi4bqLIjtzOjM6IuG6iiI7czozOiLhuo0i
|
||||
O3M6Mzoi4bqMIjtzOjM6IuG6jyI7czozOiLhuo4iO3M6Mzoi4bqRIjtzOjM6IuG6kCI7czozOiLh
|
||||
upMiO3M6Mzoi4bqSIjtzOjM6IuG6lSI7czozOiLhupQiO3M6Mzoi4bqbIjtzOjM6IuG5oCI7czoz
|
||||
OiLhuqEiO3M6Mzoi4bqgIjtzOjM6IuG6oyI7czozOiLhuqIiO3M6Mzoi4bqlIjtzOjM6IuG6pCI7
|
||||
czozOiLhuqciO3M6Mzoi4bqmIjtzOjM6IuG6qSI7czozOiLhuqgiO3M6Mzoi4bqrIjtzOjM6IuG6
|
||||
qiI7czozOiLhuq0iO3M6Mzoi4bqsIjtzOjM6IuG6ryI7czozOiLhuq4iO3M6Mzoi4bqxIjtzOjM6
|
||||
IuG6sCI7czozOiLhurMiO3M6Mzoi4bqyIjtzOjM6IuG6tSI7czozOiLhurQiO3M6Mzoi4bq3Ijtz
|
||||
OjM6IuG6tiI7czozOiLhurkiO3M6Mzoi4bq4IjtzOjM6IuG6uyI7czozOiLhuroiO3M6Mzoi4bq9
|
||||
IjtzOjM6IuG6vCI7czozOiLhur8iO3M6Mzoi4bq+IjtzOjM6IuG7gSI7czozOiLhu4AiO3M6Mzoi
|
||||
4buDIjtzOjM6IuG7giI7czozOiLhu4UiO3M6Mzoi4buEIjtzOjM6IuG7hyI7czozOiLhu4YiO3M6
|
||||
Mzoi4buJIjtzOjM6IuG7iCI7czozOiLhu4siO3M6Mzoi4buKIjtzOjM6IuG7jSI7czozOiLhu4wi
|
||||
O3M6Mzoi4buPIjtzOjM6IuG7jiI7czozOiLhu5EiO3M6Mzoi4buQIjtzOjM6IuG7kyI7czozOiLh
|
||||
u5IiO3M6Mzoi4buVIjtzOjM6IuG7lCI7czozOiLhu5ciO3M6Mzoi4buWIjtzOjM6IuG7mSI7czoz
|
||||
OiLhu5giO3M6Mzoi4bubIjtzOjM6IuG7miI7czozOiLhu50iO3M6Mzoi4bucIjtzOjM6IuG7nyI7
|
||||
czozOiLhu54iO3M6Mzoi4buhIjtzOjM6IuG7oCI7czozOiLhu6MiO3M6Mzoi4buiIjtzOjM6IuG7
|
||||
pSI7czozOiLhu6QiO3M6Mzoi4bunIjtzOjM6IuG7piI7czozOiLhu6kiO3M6Mzoi4buoIjtzOjM6
|
||||
IuG7qyI7czozOiLhu6oiO3M6Mzoi4butIjtzOjM6IuG7rCI7czozOiLhu68iO3M6Mzoi4buuIjtz
|
||||
OjM6IuG7sSI7czozOiLhu7AiO3M6Mzoi4buzIjtzOjM6IuG7siI7czozOiLhu7UiO3M6Mzoi4bu0
|
||||
IjtzOjM6IuG7tyI7czozOiLhu7YiO3M6Mzoi4bu5IjtzOjM6IuG7uCI7czozOiLhu7siO3M6Mzoi
|
||||
4bu6IjtzOjM6IuG7vSI7czozOiLhu7wiO3M6Mzoi4bu/IjtzOjM6IuG7viI7czozOiLhvIAiO3M6
|
||||
Mzoi4byIIjtzOjM6IuG8gSI7czozOiLhvIkiO3M6Mzoi4byCIjtzOjM6IuG8iiI7czozOiLhvIMi
|
||||
O3M6Mzoi4byLIjtzOjM6IuG8hCI7czozOiLhvIwiO3M6Mzoi4byFIjtzOjM6IuG8jSI7czozOiLh
|
||||
vIYiO3M6Mzoi4byOIjtzOjM6IuG8hyI7czozOiLhvI8iO3M6Mzoi4byQIjtzOjM6IuG8mCI7czoz
|
||||
OiLhvJEiO3M6Mzoi4byZIjtzOjM6IuG8kiI7czozOiLhvJoiO3M6Mzoi4byTIjtzOjM6IuG8myI7
|
||||
czozOiLhvJQiO3M6Mzoi4bycIjtzOjM6IuG8lSI7czozOiLhvJ0iO3M6Mzoi4bygIjtzOjM6IuG8
|
||||
qCI7czozOiLhvKEiO3M6Mzoi4bypIjtzOjM6IuG8oiI7czozOiLhvKoiO3M6Mzoi4byjIjtzOjM6
|
||||
IuG8qyI7czozOiLhvKQiO3M6Mzoi4bysIjtzOjM6IuG8pSI7czozOiLhvK0iO3M6Mzoi4bymIjtz
|
||||
OjM6IuG8riI7czozOiLhvKciO3M6Mzoi4byvIjtzOjM6IuG8sCI7czozOiLhvLgiO3M6Mzoi4byx
|
||||
IjtzOjM6IuG8uSI7czozOiLhvLIiO3M6Mzoi4by6IjtzOjM6IuG8syI7czozOiLhvLsiO3M6Mzoi
|
||||
4by0IjtzOjM6IuG8vCI7czozOiLhvLUiO3M6Mzoi4by9IjtzOjM6IuG8tiI7czozOiLhvL4iO3M6
|
||||
Mzoi4by3IjtzOjM6IuG8vyI7czozOiLhvYAiO3M6Mzoi4b2IIjtzOjM6IuG9gSI7czozOiLhvYki
|
||||
O3M6Mzoi4b2CIjtzOjM6IuG9iiI7czozOiLhvYMiO3M6Mzoi4b2LIjtzOjM6IuG9hCI7czozOiLh
|
||||
vYwiO3M6Mzoi4b2FIjtzOjM6IuG9jSI7czozOiLhvZEiO3M6Mzoi4b2ZIjtzOjM6IuG9kyI7czoz
|
||||
OiLhvZsiO3M6Mzoi4b2VIjtzOjM6IuG9nSI7czozOiLhvZciO3M6Mzoi4b2fIjtzOjM6IuG9oCI7
|
||||
czozOiLhvagiO3M6Mzoi4b2hIjtzOjM6IuG9qSI7czozOiLhvaIiO3M6Mzoi4b2qIjtzOjM6IuG9
|
||||
oyI7czozOiLhvasiO3M6Mzoi4b2kIjtzOjM6IuG9rCI7czozOiLhvaUiO3M6Mzoi4b2tIjtzOjM6
|
||||
IuG9piI7czozOiLhva4iO3M6Mzoi4b2nIjtzOjM6IuG9ryI7czozOiLhvbAiO3M6Mzoi4b66Ijtz
|
||||
OjM6IuG9sSI7czozOiLhvrsiO3M6Mzoi4b2yIjtzOjM6IuG/iCI7czozOiLhvbMiO3M6Mzoi4b+J
|
||||
IjtzOjM6IuG9tCI7czozOiLhv4oiO3M6Mzoi4b21IjtzOjM6IuG/iyI7czozOiLhvbYiO3M6Mzoi
|
||||
4b+aIjtzOjM6IuG9tyI7czozOiLhv5siO3M6Mzoi4b24IjtzOjM6IuG/uCI7czozOiLhvbkiO3M6
|
||||
Mzoi4b+5IjtzOjM6IuG9uiI7czozOiLhv6oiO3M6Mzoi4b27IjtzOjM6IuG/qyI7czozOiLhvbwi
|
||||
O3M6Mzoi4b+6IjtzOjM6IuG9vSI7czozOiLhv7siO3M6Mzoi4b6AIjtzOjM6IuG+iCI7czozOiLh
|
||||
voEiO3M6Mzoi4b6JIjtzOjM6IuG+giI7czozOiLhvooiO3M6Mzoi4b6DIjtzOjM6IuG+iyI7czoz
|
||||
OiLhvoQiO3M6Mzoi4b6MIjtzOjM6IuG+hSI7czozOiLhvo0iO3M6Mzoi4b6GIjtzOjM6IuG+jiI7
|
||||
czozOiLhvociO3M6Mzoi4b6PIjtzOjM6IuG+kCI7czozOiLhvpgiO3M6Mzoi4b6RIjtzOjM6IuG+
|
||||
mSI7czozOiLhvpIiO3M6Mzoi4b6aIjtzOjM6IuG+kyI7czozOiLhvpsiO3M6Mzoi4b6UIjtzOjM6
|
||||
IuG+nCI7czozOiLhvpUiO3M6Mzoi4b6dIjtzOjM6IuG+liI7czozOiLhvp4iO3M6Mzoi4b6XIjtz
|
||||
OjM6IuG+nyI7czozOiLhvqAiO3M6Mzoi4b6oIjtzOjM6IuG+oSI7czozOiLhvqkiO3M6Mzoi4b6i
|
||||
IjtzOjM6IuG+qiI7czozOiLhvqMiO3M6Mzoi4b6rIjtzOjM6IuG+pCI7czozOiLhvqwiO3M6Mzoi
|
||||
4b6lIjtzOjM6IuG+rSI7czozOiLhvqYiO3M6Mzoi4b6uIjtzOjM6IuG+pyI7czozOiLhvq8iO3M6
|
||||
Mzoi4b6wIjtzOjM6IuG+uCI7czozOiLhvrEiO3M6Mzoi4b65IjtzOjM6IuG+syI7czozOiLhvrwi
|
||||
O3M6Mzoi4b6+IjtzOjI6Is6ZIjtzOjM6IuG/gyI7czozOiLhv4wiO3M6Mzoi4b+QIjtzOjM6IuG/
|
||||
mCI7czozOiLhv5EiO3M6Mzoi4b+ZIjtzOjM6IuG/oCI7czozOiLhv6giO3M6Mzoi4b+hIjtzOjM6
|
||||
IuG/qSI7czozOiLhv6UiO3M6Mzoi4b+sIjtzOjM6IuG/syI7czozOiLhv7wiO3M6Mzoi4oWOIjtz
|
||||
OjM6IuKEsiI7czozOiLihbAiO3M6Mzoi4oWgIjtzOjM6IuKFsSI7czozOiLihaEiO3M6Mzoi4oWy
|
||||
IjtzOjM6IuKFoiI7czozOiLihbMiO3M6Mzoi4oWjIjtzOjM6IuKFtCI7czozOiLihaQiO3M6Mzoi
|
||||
4oW1IjtzOjM6IuKFpSI7czozOiLihbYiO3M6Mzoi4oWmIjtzOjM6IuKFtyI7czozOiLihaciO3M6
|
||||
Mzoi4oW4IjtzOjM6IuKFqCI7czozOiLihbkiO3M6Mzoi4oWpIjtzOjM6IuKFuiI7czozOiLihaoi
|
||||
O3M6Mzoi4oW7IjtzOjM6IuKFqyI7czozOiLihbwiO3M6Mzoi4oWsIjtzOjM6IuKFvSI7czozOiLi
|
||||
ha0iO3M6Mzoi4oW+IjtzOjM6IuKFriI7czozOiLihb8iO3M6Mzoi4oWvIjtzOjM6IuKGhCI7czoz
|
||||
OiLihoMiO3M6Mzoi4pOQIjtzOjM6IuKStiI7czozOiLik5EiO3M6Mzoi4pK3IjtzOjM6IuKTkiI7
|
||||
czozOiLikrgiO3M6Mzoi4pOTIjtzOjM6IuKSuSI7czozOiLik5QiO3M6Mzoi4pK6IjtzOjM6IuKT
|
||||
lSI7czozOiLikrsiO3M6Mzoi4pOWIjtzOjM6IuKSvCI7czozOiLik5ciO3M6Mzoi4pK9IjtzOjM6
|
||||
IuKTmCI7czozOiLikr4iO3M6Mzoi4pOZIjtzOjM6IuKSvyI7czozOiLik5oiO3M6Mzoi4pOAIjtz
|
||||
OjM6IuKTmyI7czozOiLik4EiO3M6Mzoi4pOcIjtzOjM6IuKTgiI7czozOiLik50iO3M6Mzoi4pOD
|
||||
IjtzOjM6IuKTniI7czozOiLik4QiO3M6Mzoi4pOfIjtzOjM6IuKThSI7czozOiLik6AiO3M6Mzoi
|
||||
4pOGIjtzOjM6IuKToSI7czozOiLik4ciO3M6Mzoi4pOiIjtzOjM6IuKTiCI7czozOiLik6MiO3M6
|
||||
Mzoi4pOJIjtzOjM6IuKTpCI7czozOiLik4oiO3M6Mzoi4pOlIjtzOjM6IuKTiyI7czozOiLik6Yi
|
||||
O3M6Mzoi4pOMIjtzOjM6IuKTpyI7czozOiLik40iO3M6Mzoi4pOoIjtzOjM6IuKTjiI7czozOiLi
|
||||
k6kiO3M6Mzoi4pOPIjtzOjM6IuKwsCI7czozOiLisIAiO3M6Mzoi4rCxIjtzOjM6IuKwgSI7czoz
|
||||
OiLisLIiO3M6Mzoi4rCCIjtzOjM6IuKwsyI7czozOiLisIMiO3M6Mzoi4rC0IjtzOjM6IuKwhCI7
|
||||
czozOiLisLUiO3M6Mzoi4rCFIjtzOjM6IuKwtiI7czozOiLisIYiO3M6Mzoi4rC3IjtzOjM6IuKw
|
||||
hyI7czozOiLisLgiO3M6Mzoi4rCIIjtzOjM6IuKwuSI7czozOiLisIkiO3M6Mzoi4rC6IjtzOjM6
|
||||
IuKwiiI7czozOiLisLsiO3M6Mzoi4rCLIjtzOjM6IuKwvCI7czozOiLisIwiO3M6Mzoi4rC9Ijtz
|
||||
OjM6IuKwjSI7czozOiLisL4iO3M6Mzoi4rCOIjtzOjM6IuKwvyI7czozOiLisI8iO3M6Mzoi4rGA
|
||||
IjtzOjM6IuKwkCI7czozOiLisYEiO3M6Mzoi4rCRIjtzOjM6IuKxgiI7czozOiLisJIiO3M6Mzoi
|
||||
4rGDIjtzOjM6IuKwkyI7czozOiLisYQiO3M6Mzoi4rCUIjtzOjM6IuKxhSI7czozOiLisJUiO3M6
|
||||
Mzoi4rGGIjtzOjM6IuKwliI7czozOiLisYciO3M6Mzoi4rCXIjtzOjM6IuKxiCI7czozOiLisJgi
|
||||
O3M6Mzoi4rGJIjtzOjM6IuKwmSI7czozOiLisYoiO3M6Mzoi4rCaIjtzOjM6IuKxiyI7czozOiLi
|
||||
sJsiO3M6Mzoi4rGMIjtzOjM6IuKwnCI7czozOiLisY0iO3M6Mzoi4rCdIjtzOjM6IuKxjiI7czoz
|
||||
OiLisJ4iO3M6Mzoi4rGPIjtzOjM6IuKwnyI7czozOiLisZAiO3M6Mzoi4rCgIjtzOjM6IuKxkSI7
|
||||
czozOiLisKEiO3M6Mzoi4rGSIjtzOjM6IuKwoiI7czozOiLisZMiO3M6Mzoi4rCjIjtzOjM6IuKx
|
||||
lCI7czozOiLisKQiO3M6Mzoi4rGVIjtzOjM6IuKwpSI7czozOiLisZYiO3M6Mzoi4rCmIjtzOjM6
|
||||
IuKxlyI7czozOiLisKciO3M6Mzoi4rGYIjtzOjM6IuKwqCI7czozOiLisZkiO3M6Mzoi4rCpIjtz
|
||||
OjM6IuKxmiI7czozOiLisKoiO3M6Mzoi4rGbIjtzOjM6IuKwqyI7czozOiLisZwiO3M6Mzoi4rCs
|
||||
IjtzOjM6IuKxnSI7czozOiLisK0iO3M6Mzoi4rGeIjtzOjM6IuKwriI7czozOiLisaEiO3M6Mzoi
|
||||
4rGgIjtzOjM6IuKxpSI7czoyOiLIuiI7czozOiLisaYiO3M6MjoiyL4iO3M6Mzoi4rGoIjtzOjM6
|
||||
IuKxpyI7czozOiLisaoiO3M6Mzoi4rGpIjtzOjM6IuKxrCI7czozOiLisasiO3M6Mzoi4rGzIjtz
|
||||
OjM6IuKxsiI7czozOiLisbYiO3M6Mzoi4rG1IjtzOjM6IuKygSI7czozOiLisoAiO3M6Mzoi4rKD
|
||||
IjtzOjM6IuKygiI7czozOiLisoUiO3M6Mzoi4rKEIjtzOjM6IuKyhyI7czozOiLisoYiO3M6Mzoi
|
||||
4rKJIjtzOjM6IuKyiCI7czozOiLisosiO3M6Mzoi4rKKIjtzOjM6IuKyjSI7czozOiLisowiO3M6
|
||||
Mzoi4rKPIjtzOjM6IuKyjiI7czozOiLispEiO3M6Mzoi4rKQIjtzOjM6IuKykyI7czozOiLispIi
|
||||
O3M6Mzoi4rKVIjtzOjM6IuKylCI7czozOiLispciO3M6Mzoi4rKWIjtzOjM6IuKymSI7czozOiLi
|
||||
spgiO3M6Mzoi4rKbIjtzOjM6IuKymiI7czozOiLisp0iO3M6Mzoi4rKcIjtzOjM6IuKynyI7czoz
|
||||
OiLisp4iO3M6Mzoi4rKhIjtzOjM6IuKyoCI7czozOiLisqMiO3M6Mzoi4rKiIjtzOjM6IuKypSI7
|
||||
czozOiLisqQiO3M6Mzoi4rKnIjtzOjM6IuKypiI7czozOiLisqkiO3M6Mzoi4rKoIjtzOjM6IuKy
|
||||
qyI7czozOiLisqoiO3M6Mzoi4rKtIjtzOjM6IuKyrCI7czozOiLisq8iO3M6Mzoi4rKuIjtzOjM6
|
||||
IuKysSI7czozOiLisrAiO3M6Mzoi4rKzIjtzOjM6IuKysiI7czozOiLisrUiO3M6Mzoi4rK0Ijtz
|
||||
OjM6IuKytyI7czozOiLisrYiO3M6Mzoi4rK5IjtzOjM6IuKyuCI7czozOiLisrsiO3M6Mzoi4rK6
|
||||
IjtzOjM6IuKyvSI7czozOiLisrwiO3M6Mzoi4rK/IjtzOjM6IuKyviI7czozOiLis4EiO3M6Mzoi
|
||||
4rOAIjtzOjM6IuKzgyI7czozOiLis4IiO3M6Mzoi4rOFIjtzOjM6IuKzhCI7czozOiLis4ciO3M6
|
||||
Mzoi4rOGIjtzOjM6IuKziSI7czozOiLis4giO3M6Mzoi4rOLIjtzOjM6IuKziiI7czozOiLis40i
|
||||
O3M6Mzoi4rOMIjtzOjM6IuKzjyI7czozOiLis44iO3M6Mzoi4rORIjtzOjM6IuKzkCI7czozOiLi
|
||||
s5MiO3M6Mzoi4rOSIjtzOjM6IuKzlSI7czozOiLis5QiO3M6Mzoi4rOXIjtzOjM6IuKzliI7czoz
|
||||
OiLis5kiO3M6Mzoi4rOYIjtzOjM6IuKzmyI7czozOiLis5oiO3M6Mzoi4rOdIjtzOjM6IuKznCI7
|
||||
czozOiLis58iO3M6Mzoi4rOeIjtzOjM6IuKzoSI7czozOiLis6AiO3M6Mzoi4rOjIjtzOjM6IuKz
|
||||
oiI7czozOiLis6wiO3M6Mzoi4rOrIjtzOjM6IuKzriI7czozOiLis60iO3M6Mzoi4rOzIjtzOjM6
|
||||
IuKzsiI7czozOiLitIAiO3M6Mzoi4YKgIjtzOjM6IuK0gSI7czozOiLhgqEiO3M6Mzoi4rSCIjtz
|
||||
OjM6IuGCoiI7czozOiLitIMiO3M6Mzoi4YKjIjtzOjM6IuK0hCI7czozOiLhgqQiO3M6Mzoi4rSF
|
||||
IjtzOjM6IuGCpSI7czozOiLitIYiO3M6Mzoi4YKmIjtzOjM6IuK0hyI7czozOiLhgqciO3M6Mzoi
|
||||
4rSIIjtzOjM6IuGCqCI7czozOiLitIkiO3M6Mzoi4YKpIjtzOjM6IuK0iiI7czozOiLhgqoiO3M6
|
||||
Mzoi4rSLIjtzOjM6IuGCqyI7czozOiLitIwiO3M6Mzoi4YKsIjtzOjM6IuK0jSI7czozOiLhgq0i
|
||||
O3M6Mzoi4rSOIjtzOjM6IuGCriI7czozOiLitI8iO3M6Mzoi4YKvIjtzOjM6IuK0kCI7czozOiLh
|
||||
grAiO3M6Mzoi4rSRIjtzOjM6IuGCsSI7czozOiLitJIiO3M6Mzoi4YKyIjtzOjM6IuK0kyI7czoz
|
||||
OiLhgrMiO3M6Mzoi4rSUIjtzOjM6IuGCtCI7czozOiLitJUiO3M6Mzoi4YK1IjtzOjM6IuK0liI7
|
||||
czozOiLhgrYiO3M6Mzoi4rSXIjtzOjM6IuGCtyI7czozOiLitJgiO3M6Mzoi4YK4IjtzOjM6IuK0
|
||||
mSI7czozOiLhgrkiO3M6Mzoi4rSaIjtzOjM6IuGCuiI7czozOiLitJsiO3M6Mzoi4YK7IjtzOjM6
|
||||
IuK0nCI7czozOiLhgrwiO3M6Mzoi4rSdIjtzOjM6IuGCvSI7czozOiLitJ4iO3M6Mzoi4YK+Ijtz
|
||||
OjM6IuK0nyI7czozOiLhgr8iO3M6Mzoi4rSgIjtzOjM6IuGDgCI7czozOiLitKEiO3M6Mzoi4YOB
|
||||
IjtzOjM6IuK0oiI7czozOiLhg4IiO3M6Mzoi4rSjIjtzOjM6IuGDgyI7czozOiLitKQiO3M6Mzoi
|
||||
4YOEIjtzOjM6IuK0pSI7czozOiLhg4UiO3M6Mzoi4rSnIjtzOjM6IuGDhyI7czozOiLitK0iO3M6
|
||||
Mzoi4YONIjtzOjM6IuqZgSI7czozOiLqmYAiO3M6Mzoi6pmDIjtzOjM6IuqZgiI7czozOiLqmYUi
|
||||
O3M6Mzoi6pmEIjtzOjM6IuqZhyI7czozOiLqmYYiO3M6Mzoi6pmJIjtzOjM6IuqZiCI7czozOiLq
|
||||
mYsiO3M6Mzoi6pmKIjtzOjM6IuqZjSI7czozOiLqmYwiO3M6Mzoi6pmPIjtzOjM6IuqZjiI7czoz
|
||||
OiLqmZEiO3M6Mzoi6pmQIjtzOjM6IuqZkyI7czozOiLqmZIiO3M6Mzoi6pmVIjtzOjM6IuqZlCI7
|
||||
czozOiLqmZciO3M6Mzoi6pmWIjtzOjM6IuqZmSI7czozOiLqmZgiO3M6Mzoi6pmbIjtzOjM6IuqZ
|
||||
miI7czozOiLqmZ0iO3M6Mzoi6pmcIjtzOjM6IuqZnyI7czozOiLqmZ4iO3M6Mzoi6pmhIjtzOjM6
|
||||
IuqZoCI7czozOiLqmaMiO3M6Mzoi6pmiIjtzOjM6IuqZpSI7czozOiLqmaQiO3M6Mzoi6pmnIjtz
|
||||
OjM6IuqZpiI7czozOiLqmakiO3M6Mzoi6pmoIjtzOjM6IuqZqyI7czozOiLqmaoiO3M6Mzoi6pmt
|
||||
IjtzOjM6IuqZrCI7czozOiLqmoEiO3M6Mzoi6pqAIjtzOjM6IuqagyI7czozOiLqmoIiO3M6Mzoi
|
||||
6pqFIjtzOjM6IuqahCI7czozOiLqmociO3M6Mzoi6pqGIjtzOjM6IuqaiSI7czozOiLqmogiO3M6
|
||||
Mzoi6pqLIjtzOjM6IuqaiiI7czozOiLqmo0iO3M6Mzoi6pqMIjtzOjM6IuqajyI7czozOiLqmo4i
|
||||
O3M6Mzoi6pqRIjtzOjM6IuqakCI7czozOiLqmpMiO3M6Mzoi6pqSIjtzOjM6IuqalSI7czozOiLq
|
||||
mpQiO3M6Mzoi6pqXIjtzOjM6IuqaliI7czozOiLqnKMiO3M6Mzoi6pyiIjtzOjM6IuqcpSI7czoz
|
||||
OiLqnKQiO3M6Mzoi6pynIjtzOjM6IuqcpiI7czozOiLqnKkiO3M6Mzoi6pyoIjtzOjM6IuqcqyI7
|
||||
czozOiLqnKoiO3M6Mzoi6pytIjtzOjM6IuqcrCI7czozOiLqnK8iO3M6Mzoi6pyuIjtzOjM6Iuqc
|
||||
syI7czozOiLqnLIiO3M6Mzoi6py1IjtzOjM6IuqctCI7czozOiLqnLciO3M6Mzoi6py2IjtzOjM6
|
||||
IuqcuSI7czozOiLqnLgiO3M6Mzoi6py7IjtzOjM6IuqcuiI7czozOiLqnL0iO3M6Mzoi6py8Ijtz
|
||||
OjM6IuqcvyI7czozOiLqnL4iO3M6Mzoi6p2BIjtzOjM6IuqdgCI7czozOiLqnYMiO3M6Mzoi6p2C
|
||||
IjtzOjM6IuqdhSI7czozOiLqnYQiO3M6Mzoi6p2HIjtzOjM6IuqdhiI7czozOiLqnYkiO3M6Mzoi
|
||||
6p2IIjtzOjM6IuqdiyI7czozOiLqnYoiO3M6Mzoi6p2NIjtzOjM6IuqdjCI7czozOiLqnY8iO3M6
|
||||
Mzoi6p2OIjtzOjM6IuqdkSI7czozOiLqnZAiO3M6Mzoi6p2TIjtzOjM6IuqdkiI7czozOiLqnZUi
|
||||
O3M6Mzoi6p2UIjtzOjM6IuqdlyI7czozOiLqnZYiO3M6Mzoi6p2ZIjtzOjM6IuqdmCI7czozOiLq
|
||||
nZsiO3M6Mzoi6p2aIjtzOjM6IuqdnSI7czozOiLqnZwiO3M6Mzoi6p2fIjtzOjM6IuqdniI7czoz
|
||||
OiLqnaEiO3M6Mzoi6p2gIjtzOjM6IuqdoyI7czozOiLqnaIiO3M6Mzoi6p2lIjtzOjM6IuqdpCI7
|
||||
czozOiLqnaciO3M6Mzoi6p2mIjtzOjM6IuqdqSI7czozOiLqnagiO3M6Mzoi6p2rIjtzOjM6Iuqd
|
||||
qiI7czozOiLqna0iO3M6Mzoi6p2sIjtzOjM6IuqdryI7czozOiLqna4iO3M6Mzoi6p26IjtzOjM6
|
||||
IuqduSI7czozOiLqnbwiO3M6Mzoi6p27IjtzOjM6IuqdvyI7czozOiLqnb4iO3M6Mzoi6p6BIjtz
|
||||
OjM6IuqegCI7czozOiLqnoMiO3M6Mzoi6p6CIjtzOjM6IuqehSI7czozOiLqnoQiO3M6Mzoi6p6H
|
||||
IjtzOjM6IuqehiI7czozOiLqnowiO3M6Mzoi6p6LIjtzOjM6IuqekSI7czozOiLqnpAiO3M6Mzoi
|
||||
6p6TIjtzOjM6IuqekiI7czozOiLqnqEiO3M6Mzoi6p6gIjtzOjM6IuqeoyI7czozOiLqnqIiO3M6
|
||||
Mzoi6p6lIjtzOjM6IuqepCI7czozOiLqnqciO3M6Mzoi6p6mIjtzOjM6IuqeqSI7czozOiLqnqgi
|
||||
O3M6Mzoi772BIjtzOjM6Iu+8oSI7czozOiLvvYIiO3M6Mzoi77yiIjtzOjM6Iu+9gyI7czozOiLv
|
||||
vKMiO3M6Mzoi772EIjtzOjM6Iu+8pCI7czozOiLvvYUiO3M6Mzoi77ylIjtzOjM6Iu+9hiI7czoz
|
||||
OiLvvKYiO3M6Mzoi772HIjtzOjM6Iu+8pyI7czozOiLvvYgiO3M6Mzoi77yoIjtzOjM6Iu+9iSI7
|
||||
czozOiLvvKkiO3M6Mzoi772KIjtzOjM6Iu+8qiI7czozOiLvvYsiO3M6Mzoi77yrIjtzOjM6Iu+9
|
||||
jCI7czozOiLvvKwiO3M6Mzoi772NIjtzOjM6Iu+8rSI7czozOiLvvY4iO3M6Mzoi77yuIjtzOjM6
|
||||
Iu+9jyI7czozOiLvvK8iO3M6Mzoi772QIjtzOjM6Iu+8sCI7czozOiLvvZEiO3M6Mzoi77yxIjtz
|
||||
OjM6Iu+9kiI7czozOiLvvLIiO3M6Mzoi772TIjtzOjM6Iu+8syI7czozOiLvvZQiO3M6Mzoi77y0
|
||||
IjtzOjM6Iu+9lSI7czozOiLvvLUiO3M6Mzoi772WIjtzOjM6Iu+8tiI7czozOiLvvZciO3M6Mzoi
|
||||
77y3IjtzOjM6Iu+9mCI7czozOiLvvLgiO3M6Mzoi772ZIjtzOjM6Iu+8uSI7czozOiLvvZoiO3M6
|
||||
Mzoi77y6IjtzOjQ6IvCQkKgiO3M6NDoi8JCQgCI7czo0OiLwkJCpIjtzOjQ6IvCQkIEiO3M6NDoi
|
||||
8JCQqiI7czo0OiLwkJCCIjtzOjQ6IvCQkKsiO3M6NDoi8JCQgyI7czo0OiLwkJCsIjtzOjQ6IvCQ
|
||||
kIQiO3M6NDoi8JCQrSI7czo0OiLwkJCFIjtzOjQ6IvCQkK4iO3M6NDoi8JCQhiI7czo0OiLwkJCv
|
||||
IjtzOjQ6IvCQkIciO3M6NDoi8JCQsCI7czo0OiLwkJCIIjtzOjQ6IvCQkLEiO3M6NDoi8JCQiSI7
|
||||
czo0OiLwkJCyIjtzOjQ6IvCQkIoiO3M6NDoi8JCQsyI7czo0OiLwkJCLIjtzOjQ6IvCQkLQiO3M6
|
||||
NDoi8JCQjCI7czo0OiLwkJC1IjtzOjQ6IvCQkI0iO3M6NDoi8JCQtiI7czo0OiLwkJCOIjtzOjQ6
|
||||
IvCQkLciO3M6NDoi8JCQjyI7czo0OiLwkJC4IjtzOjQ6IvCQkJAiO3M6NDoi8JCQuSI7czo0OiLw
|
||||
kJCRIjtzOjQ6IvCQkLoiO3M6NDoi8JCQkiI7czo0OiLwkJC7IjtzOjQ6IvCQkJMiO3M6NDoi8JCQ
|
||||
vCI7czo0OiLwkJCUIjtzOjQ6IvCQkL0iO3M6NDoi8JCQlSI7czo0OiLwkJC+IjtzOjQ6IvCQkJYi
|
||||
O3M6NDoi8JCQvyI7czo0OiLwkJCXIjtzOjQ6IvCQkYAiO3M6NDoi8JCQmCI7czo0OiLwkJGBIjtz
|
||||
OjQ6IvCQkJkiO3M6NDoi8JCRgiI7czo0OiLwkJCaIjtzOjQ6IvCQkYMiO3M6NDoi8JCQmyI7czo0
|
||||
OiLwkJGEIjtzOjQ6IvCQkJwiO3M6NDoi8JCRhSI7czo0OiLwkJCdIjtzOjQ6IvCQkYYiO3M6NDoi
|
||||
8JCQniI7czo0OiLwkJGHIjtzOjQ6IvCQkJ8iO3M6NDoi8JCRiCI7czo0OiLwkJCgIjtzOjQ6IvCQ
|
||||
kYkiO3M6NDoi8JCQoSI7czo0OiLwkJGKIjtzOjQ6IvCQkKIiO3M6NDoi8JCRiyI7czo0OiLwkJCj
|
||||
IjtzOjQ6IvCQkYwiO3M6NDoi8JCQpCI7czo0OiLwkJGNIjtzOjQ6IvCQkKUiO3M6NDoi8JCRjiI7
|
||||
czo0OiLwkJCmIjtzOjQ6IvCQkY8iO3M6NDoi8JCQpyI7fQ=='));
|
||||
$map = $upper;
|
||||
|
||||
static $ulen_mask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
|
||||
|
||||
$i = 0;
|
||||
$len = strlen($s);
|
||||
|
||||
while ($i < $len)
|
||||
{
|
||||
$ulen = $s[$i] < "\x80" ? 1 : $ulen_mask[$s[$i] & "\xF0"];
|
||||
$uchr = substr($s, $i, $ulen);
|
||||
$i += $ulen;
|
||||
|
||||
if (isset($map[$uchr]))
|
||||
{
|
||||
$uchr = $map[$uchr];
|
||||
$nlen = strlen($uchr);
|
||||
|
||||
if ($nlen == $ulen)
|
||||
{
|
||||
$nlen = $i;
|
||||
do $s[--$nlen] = $uchr[--$ulen];
|
||||
while ($ulen);
|
||||
}
|
||||
else
|
||||
{
|
||||
$s = substr_replace($s, $uchr, $i - $ulen, $ulen);
|
||||
$len += $nlen - $ulen;
|
||||
$i += $nlen - $ulen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (INF === $encoding) return $s;
|
||||
else return function_exists('iconv') ? iconv('UTF-8', $encoding, $s) : $s;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('mb_strcut'))
|
||||
{
|
||||
function mb_strcut($str, $start, $length = null, $encoding = '')
|
||||
{
|
||||
$match = array();
|
||||
// use the regex unicode support to separate the UTF-8 characters into an array
|
||||
preg_match_all( '/./us', $str, $match );
|
||||
$chars = is_null( $length )? array_slice( $match[0], $start ) : array_slice( $match[0], $start, $length );
|
||||
return implode( '', $chars );
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('mb_detect_encoding'))
|
||||
{
|
||||
function mb_detect_encoding($str, $encoding_list = INF, $strict = false)
|
||||
{
|
||||
if (INF === $encoding_list) $encoding_list = 'UTF-8';
|
||||
else
|
||||
{
|
||||
if (! is_array($encoding_list)) $encoding_list = array_map('trim', explode(',', $encoding_list));
|
||||
$encoding_list = array_map('strtoupper', $encoding_list);
|
||||
}
|
||||
|
||||
foreach ($encoding_list as $enc)
|
||||
{
|
||||
switch ($enc)
|
||||
{
|
||||
case 'ASCII':
|
||||
if (! preg_match('/[\x80-\xFF]/', $str)) return $enc;
|
||||
break;
|
||||
|
||||
case 'UTF8':
|
||||
case 'UTF-8':
|
||||
if (preg_match('//u', $str)) return $enc;
|
||||
break;
|
||||
|
||||
default:
|
||||
return strncmp($enc, 'ISO-8859-', 9) ? false : $enc;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('mb_check_encoding'))
|
||||
{
|
||||
function mb_check_encoding($var = INF, $encoding = INF)
|
||||
{
|
||||
if (INF === $encoding)
|
||||
{
|
||||
if (INF === $var) return false;
|
||||
$encoding = 'UTF-8';
|
||||
}
|
||||
|
||||
return false !== mb_detect_encoding($var, array($encoding), true);
|
||||
}
|
||||
}
|
||||
560
rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php
Normal file
560
rainloop/v/0.0.0/app/libraries/RainLoop/Common/PdoAbstract.php
Normal file
|
|
@ -0,0 +1,560 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Common;
|
||||
|
||||
abstract class PdoAbstract
|
||||
{
|
||||
/**
|
||||
* @var \PDO
|
||||
*/
|
||||
protected $oPDO = null;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $bExplain = false;
|
||||
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
protected $oLogger;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $sDbType;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsSupported()
|
||||
{
|
||||
return !!\class_exists('PDO');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Log\Logger $oLogger
|
||||
*/
|
||||
public function SetLogger($oLogger)
|
||||
{
|
||||
$this->oLogger = $oLogger instanceof \MailSo\Log\Logger ? $oLogger : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function getPdoAccessData()
|
||||
{
|
||||
return array('', '', '', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \PDO
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function getPDO()
|
||||
{
|
||||
if ($this->oPDO)
|
||||
{
|
||||
return $this->oPDO;
|
||||
}
|
||||
|
||||
if (!\class_exists('PDO'))
|
||||
{
|
||||
throw new \Exception('Class PDO does not exist');
|
||||
}
|
||||
|
||||
$sType = $sDsn = $sDbLogin = $sDbPassword = '';
|
||||
list($sType, $sDsn, $sDbLogin, $sDbPassword) = $this->getPdoAccessData();
|
||||
if (!\in_array($sType, array('mysql', 'sqlite', 'pgsql')))
|
||||
{
|
||||
throw new \Exception('Unknown PDO SQL connection type');
|
||||
}
|
||||
|
||||
if (empty($sDsn))
|
||||
{
|
||||
throw new \Exception('Empty PDO DSN configuration');
|
||||
}
|
||||
|
||||
$this->sDbType = $sType;
|
||||
|
||||
$oPdo = false;
|
||||
try
|
||||
{
|
||||
$oPdo = @new \PDO($sDsn, $sDbLogin, $sDbPassword);
|
||||
if ($oPdo)
|
||||
{
|
||||
$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
if ('mysql' === $sType && 'mysql' === $oPdo->getAttribute(\PDO::ATTR_DRIVER_NAME))
|
||||
{
|
||||
$oPdo->exec('SET NAMES utf8 COLLATE utf8_general_ci');
|
||||
// $oPdo->exec('SET NAMES utf8');
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
throw $oException;
|
||||
}
|
||||
|
||||
if ($oPdo)
|
||||
{
|
||||
$this->oPDO = $oPdo;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \Exception('PDO = false');
|
||||
}
|
||||
|
||||
return $oPdo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTabelName = null
|
||||
* @param string $sColumnName = null
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function lastInsertId($sTabelName = null, $sColumnName = null)
|
||||
{
|
||||
$mName = null;
|
||||
if ('pgsql' === $this->sDbType &&
|
||||
null !== $sTabelName && $sColumnName !== null)
|
||||
{
|
||||
$mName = \strtolower($sTabelName.'_'.$sColumnName.'_seq');
|
||||
}
|
||||
|
||||
return null === $mName ? $this->getPDO()->lastInsertId() : $this->getPDO()->lastInsertId($mName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function beginTransaction()
|
||||
{
|
||||
return $this->getPDO()->beginTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function commit()
|
||||
{
|
||||
return $this->getPDO()->commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function rollBack()
|
||||
{
|
||||
return $this->getPDO()->rollBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSql
|
||||
* @param array $aParams
|
||||
* @param bool $bMultiplyParams = false
|
||||
*
|
||||
* @return \PDOStatement|null
|
||||
*/
|
||||
protected function prepareAndExecute($sSql, $aParams = array(), $bMultiplyParams = false)
|
||||
{
|
||||
if ($this->bExplain && !$bMultiplyParams)
|
||||
{
|
||||
$this->prepareAndExplain($sSql, $aParams);
|
||||
}
|
||||
|
||||
$mResult = null;
|
||||
|
||||
$this->writeLog($sSql);
|
||||
$oStmt = $this->getPDO()->prepare($sSql);
|
||||
if ($oStmt)
|
||||
{
|
||||
$aRootParams = $bMultiplyParams ? $aParams : array($aParams);
|
||||
foreach ($aRootParams as $aSubParams)
|
||||
{
|
||||
foreach ($aSubParams as $sName => $aValue)
|
||||
{
|
||||
$oStmt->bindValue($sName, $aValue[0], $aValue[1]);
|
||||
}
|
||||
|
||||
$mResult = $oStmt->execute() && !$bMultiplyParams ? $oStmt : null;
|
||||
}
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSql
|
||||
* @param array $aParams
|
||||
*/
|
||||
protected function prepareAndExplain($sSql, $aParams = array())
|
||||
{
|
||||
$mResult = null;
|
||||
if (0 === strpos($sSql, 'SELECT '))
|
||||
{
|
||||
$sSql = 'EXPLAIN '.$sSql;
|
||||
$this->writeLog($sSql);
|
||||
$oStmt = $this->getPDO()->prepare($sSql);
|
||||
if ($oStmt)
|
||||
{
|
||||
foreach ($aParams as $sName => $aValue)
|
||||
{
|
||||
$oStmt->bindValue($sName, $aValue[0], $aValue[1]);
|
||||
}
|
||||
|
||||
$mResult = $oStmt->execute() ? $oStmt : null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($mResult)
|
||||
{
|
||||
$aFetch = $mResult->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$this->oLogger->WriteDump($aFetch);
|
||||
|
||||
unset($aFetch);
|
||||
$mResult->closeCursor();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $mData
|
||||
*/
|
||||
protected function writeLog($mData)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->WriteMixed($mData, \MailSo\Log\Enumerations\Type::INFO, 'SQL');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param bool $bSkipInsert = false
|
||||
* @param bool $bCache = true
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getUserId($sEmail, $bSkipInsert = false, $bCache = true)
|
||||
{
|
||||
static $aCache = array();
|
||||
if ($bCache && isset($aCache[$sEmail]))
|
||||
{
|
||||
return $aCache[$sEmail];
|
||||
}
|
||||
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii(\trim($sEmail), true);
|
||||
if (empty($sEmail))
|
||||
{
|
||||
throw new \InvalidArgumentException('Empty Email argument');
|
||||
}
|
||||
|
||||
$oStmt = $this->prepareAndExecute('SELECT id_user FROM rainloop_users WHERE rl_email = :rl_email',
|
||||
array(
|
||||
':rl_email' => array($sEmail, \PDO::PARAM_STR)
|
||||
)
|
||||
);
|
||||
|
||||
$mRow = $oStmt->fetch(\PDO::FETCH_ASSOC);
|
||||
if ($mRow && isset($mRow['id_user']) && \is_numeric($mRow['id_user']))
|
||||
{
|
||||
$iResult = (int) $mRow['id_user'];
|
||||
if (0 >= $iResult)
|
||||
{
|
||||
throw new \Exception('id_user <= 0');
|
||||
}
|
||||
|
||||
if ($bCache)
|
||||
{
|
||||
$aCache[$sEmail] = $iResult;
|
||||
}
|
||||
|
||||
return $iResult;
|
||||
}
|
||||
|
||||
if (!$bSkipInsert)
|
||||
{
|
||||
$oStmt->closeCursor();
|
||||
|
||||
$oStmt = $this->prepareAndExecute('INSERT INTO rainloop_users (rl_email) VALUES (:rl_email)',
|
||||
array(':rl_email' => array($sEmail, \PDO::PARAM_STR))
|
||||
);
|
||||
|
||||
return $this->getUserId($sEmail, true);
|
||||
}
|
||||
|
||||
throw new \Exception('id_user = 0');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sValue
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function quoteValue($sValue)
|
||||
{
|
||||
$oPdo = $this->getPDO();
|
||||
return $oPdo ? $oPdo->quote((string) $sValue, \PDO::PARAM_STR) : '\'\'';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bReturnIntValue = true
|
||||
*
|
||||
* @return int|string|bool
|
||||
*/
|
||||
protected function getSystemValue($sName, $bReturnIntValue = true)
|
||||
{
|
||||
$oPdo = $this->getPDO();
|
||||
if ($oPdo)
|
||||
{
|
||||
if ($bReturnIntValue)
|
||||
{
|
||||
$sQuery = 'SELECT value_int FROM rainloop_system WHERE sys_name = ?';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sQuery = 'SELECT value_str FROM rainloop_system WHERE sys_name = ?';
|
||||
}
|
||||
|
||||
$this->writeLog($sQuery);
|
||||
|
||||
$oStmt = $oPdo->prepare($sQuery);
|
||||
if ($oStmt->execute(array($sName)))
|
||||
{
|
||||
$mRow = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$sKey = $bReturnIntValue ? 'value_int' : 'value_str';
|
||||
if ($mRow && isset($mRow[0][$sKey]))
|
||||
{
|
||||
return $bReturnIntValue ? (int) $mRow[0][$sKey] : (string) $mRow[0][$sKey];
|
||||
}
|
||||
|
||||
return $bReturnIntValue ? 0 : '';
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return int|string|bool
|
||||
*/
|
||||
protected function getVersion($sName)
|
||||
{
|
||||
return $this->getSystemValue($sName.'_version', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param int $iVersion
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function setVersion($sName, $iVersion)
|
||||
{
|
||||
$bResult = false;
|
||||
$oPdo = $this->getPDO();
|
||||
if ($oPdo)
|
||||
{
|
||||
$sQuery = 'DELETE FROM rainloop_system WHERE sys_name = ? AND value_int <= ?;';
|
||||
$this->writeLog($sQuery);
|
||||
|
||||
$oStmt = $oPdo->prepare($sQuery);
|
||||
$bResult = !!$oStmt->execute(array($sName.'_version', $iVersion));
|
||||
if ($bResult)
|
||||
{
|
||||
$sQuery = 'INSERT INTO rainloop_system (sys_name, value_int) VALUES (?, ?);';
|
||||
$this->writeLog($sQuery);
|
||||
|
||||
$oStmt = $oPdo->prepare($sQuery);
|
||||
if ($oStmt)
|
||||
{
|
||||
$bResult = !!$oStmt->execute(array($sName.'_version', $iVersion));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bWatchVersion = true
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function initSystemTables()
|
||||
{
|
||||
$bResult = true;
|
||||
|
||||
$oPdo = $this->getPDO();
|
||||
if ($oPdo)
|
||||
{
|
||||
$aQ = array();
|
||||
switch ($this->sDbType)
|
||||
{
|
||||
case 'mysql':
|
||||
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_system (
|
||||
sys_name varchar(50) NOT NULL,
|
||||
value_int int UNSIGNED NOT NULL DEFAULT 0,
|
||||
value_str varchar(128) NOT NULL DEFAULT \'\',
|
||||
INDEX sys_name_rainloop_system_index (sys_name)
|
||||
) /*!40000 ENGINE=INNODB *//*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;';
|
||||
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_users (
|
||||
id_user int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\',
|
||||
PRIMARY KEY(id_user),
|
||||
INDEX rl_email_rainloop_users_index (rl_email)
|
||||
) /*!40000 ENGINE=INNODB */;';
|
||||
break;
|
||||
|
||||
case 'pgsql':
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name varchar(50) NOT NULL,
|
||||
value_int integer NOT NULL DEFAULT 0,
|
||||
value_str varchar(128) NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
|
||||
$aQ[] = 'CREATE SEQUENCE id_user START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;';
|
||||
$aQ[] = 'CREATE TABLE rainloop_users (
|
||||
id_user integer DEFAULT nextval(\'id_user\'::text) PRIMARY KEY,
|
||||
rl_email varchar(128) NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
break;
|
||||
|
||||
case 'sqlite':
|
||||
$aQ[] = 'CREATE TABLE rainloop_system (
|
||||
sys_name text NOT NULL,
|
||||
value_int integer NOT NULL DEFAULT 0,
|
||||
value_str text NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
|
||||
$aQ[] = 'CREATE TABLE rainloop_users (
|
||||
id_user integer NOT NULL PRIMARY KEY,
|
||||
rl_email text NOT NULL DEFAULT \'\'
|
||||
);';
|
||||
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 < \count($aQ))
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach ($aQ as $sQuery)
|
||||
{
|
||||
if ($bResult)
|
||||
{
|
||||
$this->writeLog($sQuery);
|
||||
$bResult = false !== $oPdo->exec($sQuery);
|
||||
if (!$bResult)
|
||||
{
|
||||
$this->writeLog('Result=false');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->writeLog('Result=true');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->writeLog($oException);
|
||||
throw $oException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param array $aData = array()
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function dataBaseUpgrade($sName, $aData = array())
|
||||
{
|
||||
$iFromVersion = null;
|
||||
try
|
||||
{
|
||||
$iFromVersion = $this->getVersion($sName);
|
||||
}
|
||||
catch (\PDOException $oException)
|
||||
{
|
||||
$this->writeLog($oException);
|
||||
|
||||
try
|
||||
{
|
||||
$this->initSystemTables();
|
||||
|
||||
$iFromVersion = $this->getVersion($sName);
|
||||
}
|
||||
catch (\PDOException $oSubException)
|
||||
{
|
||||
$this->writeLog($oSubException);
|
||||
throw $oSubException;
|
||||
}
|
||||
}
|
||||
|
||||
if (\is_int($iFromVersion) && 0 <= $iFromVersion)
|
||||
{
|
||||
$oPdo = false;
|
||||
$bResult = false;
|
||||
|
||||
foreach ($aData as $iVersion => $aQuery)
|
||||
{
|
||||
if (0 === \count($aQuery))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$oPdo)
|
||||
{
|
||||
$oPdo = $this->getPDO();
|
||||
$bResult = true;
|
||||
}
|
||||
|
||||
if ($iFromVersion < $iVersion && $oPdo)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach ($aQuery as $sQuery)
|
||||
{
|
||||
$this->writeLog($sQuery);
|
||||
$bExec = $oPdo->exec($sQuery);
|
||||
if (false === $bExec)
|
||||
{
|
||||
$this->writeLog('Result: false');
|
||||
|
||||
$bResult = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->writeLog($oException);
|
||||
throw $oException;
|
||||
}
|
||||
|
||||
if (!$bResult)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$this->setVersion($sName, $iVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Common;
|
||||
|
||||
class RainLoopFacebookRedirectLoginHelper extends \Facebook\FacebookRedirectLoginHelper
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $rlAppId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $rlUserHash;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $rlAccount;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $rlStorageProvaider;
|
||||
|
||||
public function __construct($redirectUrl, $appId = null, $appSecret = null)
|
||||
{
|
||||
parent::__construct($redirectUrl, $appId, $appSecret);
|
||||
|
||||
$this->rlAppId = '';
|
||||
$this->rlUserHash = '';
|
||||
$this->rlAccount = null;
|
||||
$this->rlStorageProvaider = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetRLAppId()
|
||||
{
|
||||
return $this->rlAppId;
|
||||
}
|
||||
|
||||
public function initRainLoopData($config)
|
||||
{
|
||||
if (!empty($config['rlAppId']))
|
||||
{
|
||||
$this->rlAppId = $config['rlAppId'];
|
||||
}
|
||||
|
||||
if (!empty($config['rlStorageProvaider']))
|
||||
{
|
||||
$this->rlStorageProvaider = $config['rlStorageProvaider'];
|
||||
}
|
||||
|
||||
if (!empty($config['rlAccount']))
|
||||
{
|
||||
$this->rlAccount = $config['rlAccount'];
|
||||
}
|
||||
|
||||
if (!empty($config['rlUserHash']))
|
||||
{
|
||||
$this->rlUserHash = (string) $config['rlUserHash'];
|
||||
}
|
||||
|
||||
if (!class_exists('RainLoop\Providers\Storage\Enumerations\StorageType') || '' === $this->rlUserHash)
|
||||
{
|
||||
$this->rlStorageProvaider = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a state string in session storage for CSRF protection.
|
||||
* Developers should subclass and override this method if they want to store
|
||||
* this state in a different location.
|
||||
*
|
||||
* @param string $state
|
||||
*
|
||||
* @throws FacebookSDKException
|
||||
*/
|
||||
protected function storeState($state)
|
||||
{
|
||||
if ($this->rlStorageProvaider)
|
||||
{
|
||||
$this->rlStorageProvaider->Put(
|
||||
$this->rlAccount ? $this->rlAccount : null,
|
||||
$this->rlAccount ? \RainLoop\Providers\Storage\Enumerations\StorageType::USER :
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->generateSessionVariableName(), $state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a state string from session storage for CSRF validation. May return
|
||||
* null if no object exists. Developers should subclass and override this
|
||||
* method if they want to load the state from a different location.
|
||||
*
|
||||
* @return string|null
|
||||
*
|
||||
* @throws FacebookSDKException
|
||||
*/
|
||||
protected function loadState()
|
||||
{
|
||||
if ($this->rlStorageProvaider)
|
||||
{
|
||||
$state = $this->rlStorageProvaider->Get(
|
||||
$this->rlAccount ? $this->rlAccount : null,
|
||||
$this->rlAccount ? \RainLoop\Providers\Storage\Enumerations\StorageType::USER :
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->generateSessionVariableName(), false);
|
||||
|
||||
if (false !== $state)
|
||||
{
|
||||
$this->state = $state;
|
||||
return $this->state;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function generateSessionVariableName()
|
||||
{
|
||||
return implode('/', array('Fackebook', \md5($this->rlUserHash), 'Storage'));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Config;
|
||||
|
||||
abstract class AbstractConfig
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sFile;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aData;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bUseApcCache;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sFileHeader;
|
||||
|
||||
/**
|
||||
* @param string $sFileName
|
||||
* @param string $sFileHeader = ''
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sFileName, $sFileHeader = '')
|
||||
{
|
||||
$this->sFile = \APP_PRIVATE_DATA.'configs/'.$sFileName;
|
||||
$this->sFileHeader = $sFileHeader;
|
||||
$this->aData = $this->defaultValues();
|
||||
|
||||
$this->bUseApcCache = APP_USE_APC_CACHE &&
|
||||
\MailSo\Base\Utils::FunctionExistsAndEnabled(array('apc_fetch', 'apc_store'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected abstract function defaultValues();
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsInited()
|
||||
{
|
||||
return \is_array($this->aData) && 0 < \count($this->aData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSection
|
||||
* @param string $sName
|
||||
* @param mixed $mDefault = null
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function Get($sSection, $sName, $mDefault = null)
|
||||
{
|
||||
$mResult = $mDefault;
|
||||
if (isset($this->aData[$sSection][$sName][0]))
|
||||
{
|
||||
$mResult = $this->aData[$sSection][$sName][0];
|
||||
}
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSectionKey
|
||||
* @param string $sParamKey
|
||||
* @param mixed $mParamValue
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Set($sSectionKey, $sParamKey, $mParamValue)
|
||||
{
|
||||
if (isset($this->aData[$sSectionKey][$sParamKey][0]))
|
||||
{
|
||||
$sType = \gettype($this->aData[$sSectionKey][$sParamKey][0]);
|
||||
switch ($sType)
|
||||
{
|
||||
default:
|
||||
case 'string':
|
||||
$this->aData[$sSectionKey][$sParamKey][0] = (string) $mParamValue;
|
||||
break;
|
||||
case 'int':
|
||||
case 'integer':
|
||||
$this->aData[$sSectionKey][$sParamKey][0] = (int) $mParamValue;
|
||||
break;
|
||||
case 'bool':
|
||||
case 'boolean':
|
||||
$this->aData[$sSectionKey][$sParamKey][0] = (bool) $mParamValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ('custom' === $sSectionKey)
|
||||
{
|
||||
$this->aData[$sSectionKey][$sParamKey] = array((string) $mParamValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function cacheKey()
|
||||
{
|
||||
return 'config:'.\sha1($this->sFile).':';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function loadDataFromCache()
|
||||
{
|
||||
if ($this->bUseApcCache)
|
||||
{
|
||||
$iMTime = @\filemtime($this->sFile);
|
||||
if (\is_int($iMTime) && 0 < $iMTime)
|
||||
{
|
||||
$sKey = $this->cacheKey();
|
||||
|
||||
$iTime = \apc_fetch($sKey.'time');
|
||||
if ($iTime && $iMTime === (int) $iTime)
|
||||
{
|
||||
$aFetchData = \apc_fetch($sKey.'data');
|
||||
if (\is_array($aFetchData))
|
||||
{
|
||||
$this->aData = $aFetchData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function storeDataToCache()
|
||||
{
|
||||
if ($this->bUseApcCache)
|
||||
{
|
||||
$iMTime = @\filemtime($this->sFile);
|
||||
if (\is_int($iMTime) && 0 < $iMTime)
|
||||
{
|
||||
$sKey = $this->cacheKey();
|
||||
|
||||
\apc_store($sKey.'time', $iMTime);
|
||||
\apc_store($sKey.'data', $this->aData);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function clearCache()
|
||||
{
|
||||
if ($this->bUseApcCache)
|
||||
{
|
||||
$sKey = $this->cacheKey();
|
||||
|
||||
\apc_delete($sKey.'time');
|
||||
\apc_delete($sKey.'data');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function Load()
|
||||
{
|
||||
if (\file_exists($this->sFile) && \is_readable($this->sFile))
|
||||
{
|
||||
if ($this->loadDataFromCache())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$aData = \RainLoop\Utils::CustomParseIniFile($this->sFile, true);
|
||||
if (\is_array($aData) && 0 < count($aData))
|
||||
{
|
||||
foreach ($aData as $sSectionKey => $aSectionValue)
|
||||
{
|
||||
if (\is_array($aSectionValue))
|
||||
{
|
||||
foreach ($aSectionValue as $sParamKey => $mParamValue)
|
||||
{
|
||||
$this->Set($sSectionKey, $sParamKey, $mParamValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->storeDataToCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function Save()
|
||||
{
|
||||
if (\file_exists($this->sFile) && !\is_writable($this->sFile))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$sNewLine = "\n";
|
||||
|
||||
$aResultLines = array();
|
||||
|
||||
foreach ($this->aData as $sSectionKey => $aSectionValue)
|
||||
{
|
||||
if (\is_array($aSectionValue))
|
||||
{
|
||||
$aResultLines[] = '';
|
||||
$aResultLines[] = '['.$sSectionKey.']';
|
||||
$bFirst = true;
|
||||
|
||||
foreach ($aSectionValue as $sParamKey => $mParamValue)
|
||||
{
|
||||
if (\is_array($mParamValue))
|
||||
{
|
||||
if (!empty($mParamValue[1]))
|
||||
{
|
||||
$sDesk = \str_replace("\r", '', $mParamValue[1]);
|
||||
$aDesk = \explode("\n", $sDesk);
|
||||
$aDesk = \array_map(function (&$sLine) {
|
||||
return '; '.$sLine;
|
||||
}, $aDesk);
|
||||
|
||||
if (!$bFirst)
|
||||
{
|
||||
$aResultLines[] = '';
|
||||
}
|
||||
|
||||
$aResultLines[] = \implode($sNewLine, $aDesk);
|
||||
}
|
||||
|
||||
$bFirst = false;
|
||||
|
||||
$sValue = '""';
|
||||
switch (\gettype($mParamValue[0]))
|
||||
{
|
||||
default:
|
||||
case 'string':
|
||||
$sValue = '"'.$mParamValue[0].'"';
|
||||
break;
|
||||
case 'int':
|
||||
case 'integer':
|
||||
$sValue = $mParamValue[0];
|
||||
break;
|
||||
case 'bool':
|
||||
case 'boolean':
|
||||
$sValue = $mParamValue[0] ? 'On' : 'Off';
|
||||
break;
|
||||
}
|
||||
|
||||
$aResultLines[] = $sParamKey.' = '.$sValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->clearCache();
|
||||
return false !== \file_put_contents($this->sFile,
|
||||
(0 < \strlen($this->sFileHeader) ? $this->sFileHeader : '').
|
||||
$sNewLine.\implode($sNewLine, $aResultLines));
|
||||
}
|
||||
}
|
||||
295
rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php
Normal file
295
rainloop/v/0.0.0/app/libraries/RainLoop/Config/Application.php
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Config;
|
||||
|
||||
class Application extends \RainLoop\Config\AbstractConfig
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('application.ini',
|
||||
'; RainLoop Webmail configuration file
|
||||
; Please don\'t add custom parameters here, those will be overwritten');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPassword
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function SetPassword($sPassword)
|
||||
{
|
||||
return $this->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 && '12345' === $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'),
|
||||
'loading_description' => array('RainLoop', 'Text displayed on startup'),
|
||||
|
||||
'theme' => array('Default', 'Theme used by default'),
|
||||
'allow_themes' => array(true, 'Allow theme selection on settings screen'),
|
||||
'allow_user_background' => array(false),
|
||||
|
||||
'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(true, ''),
|
||||
|
||||
'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(25,
|
||||
'File size limit (MB) for file upload on compose screen
|
||||
0 for unlimited.')
|
||||
),
|
||||
|
||||
'interface' => array(
|
||||
'show_attachment_thumbnail' => array(true, '')
|
||||
),
|
||||
|
||||
'branding' => array(
|
||||
'login_logo' => array(''),
|
||||
'login_desc' => array(''),
|
||||
'login_css' => array(''),
|
||||
'login_powered' => array(true)
|
||||
),
|
||||
|
||||
'contacts' => array(
|
||||
'enable' => array(false, 'Enable contacts'),
|
||||
'allow_sharing' => array(true),
|
||||
'allow_sync' => array(false),
|
||||
'sync_interval' => array(20),
|
||||
'type' => array('sqlite', ''),
|
||||
'pdo_dsn' => array('mysql:host=127.0.0.1;port=3306;dbname=rainloop', ''),
|
||||
'pdo_user' => array('root', ''),
|
||||
'pdo_password' => array('', ''),
|
||||
'suggestions_limit' => array(30)
|
||||
),
|
||||
|
||||
'security' => array(
|
||||
'csrf_protection' => array(true,
|
||||
'Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)'),
|
||||
|
||||
'custom_server_signature' => array('RainLoop'),
|
||||
'x_frame_options_header' => array(''),
|
||||
'openpgp' => array(false),
|
||||
'use_rsa_encryption' => array(false),
|
||||
'admin_login' => array('admin', 'Login and password for web admin panel'),
|
||||
'admin_password' => array('12345'),
|
||||
'allow_admin_panel' => array(true, 'Access settings'),
|
||||
'allow_two_factor_auth' => array(false),
|
||||
'allow_universal_login' => array(true),
|
||||
'admin_panel_host' => array(''),
|
||||
'core_install_access_domain' => array('')
|
||||
),
|
||||
|
||||
'ssl' => array(
|
||||
'verify_certificate' => array(false, 'Require verification of SSL certificate used.'),
|
||||
'allow_self_signed' => array(true, 'Allow self-signed certificates. Requires verify_certificate.'),
|
||||
'cafile' => array('', 'Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)'),
|
||||
'capath' => array('', 'capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)'),
|
||||
),
|
||||
|
||||
'login' => array(
|
||||
|
||||
'default_domain' => array('', ''),
|
||||
|
||||
'allow_languages_on_login' => array(true,
|
||||
'Allow language selection on webmail login screen'),
|
||||
|
||||
'determine_user_language' => array(true, ''),
|
||||
'determine_user_domain' => array(false, ''),
|
||||
|
||||
'forgot_password_link_url' => array('', ''),
|
||||
'registration_link_url' => array('', ''),
|
||||
|
||||
'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 (php requred)'),
|
||||
'write_on_php_error_only' => array(false, 'Logs entire request only if php error occured'),
|
||||
'write_on_timeout_only' => array(0, 'Logs entire request only if request timeout (in seconds) occured.'),
|
||||
|
||||
'hide_passwords' => array(true, 'Required for development purposes only.
|
||||
Disabling this option is not recommended.'),
|
||||
|
||||
'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 (the user part of an email)
|
||||
If user is not logged in, value is set to "unknown"
|
||||
{user:domain} - Replaced by user\'s domain name (the domain part of an email)
|
||||
If user is not logged in, value is set to "unknown"
|
||||
{user:uid} - Replaced by user\'s UID regardless of account currently used
|
||||
{user:ip} - Replaced by user\'s IP address
|
||||
|
||||
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')
|
||||
),
|
||||
|
||||
'social' => array(
|
||||
'google_enable' => array(false, 'Google'),
|
||||
'google_enable_auth' => array(false),
|
||||
'google_enable_drive' => array(false),
|
||||
'google_enable_preview' => array(false),
|
||||
'google_client_id' => array(''),
|
||||
'google_client_secret' => array(''),
|
||||
'google_api_key' => 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(true, 'Caching message UIDs when searching and sorting (threading)')
|
||||
),
|
||||
|
||||
'labs' => array(
|
||||
'ignore_folders_subscription' => array(false,
|
||||
'Experimental settings. Handle with care.
|
||||
'),
|
||||
'check_new_password_strength' => array(true),
|
||||
'update_channel' => array('stable'),
|
||||
'allow_gravatar' => array(true),
|
||||
'allow_prefetch' => array(true),
|
||||
'allow_smart_html_links' => array(true),
|
||||
'cache_system_data' => array(true),
|
||||
'date_from_headers' => array(false),
|
||||
'autocreate_system_folders' => array(true),
|
||||
'allow_message_append' => array(false),
|
||||
'disable_iconv_if_mbstring_supported' => array(false),
|
||||
'login_fault_delay' => array(1),
|
||||
'log_ajax_response_write_limit' => array(300),
|
||||
'allow_html_editor_source_button' => array(false),
|
||||
'allow_html_editor_biti_buttons' => array(false),
|
||||
'allow_ctrl_enter_on_compose' => array(false),
|
||||
'hide_dangerous_actions' => array(false),
|
||||
'use_app_debug_js' => array(false),
|
||||
'use_app_debug_css' => array(false),
|
||||
'use_imap_sort' => array(true),
|
||||
'use_imap_esearch_esort' => array(true),
|
||||
'use_imap_force_selection' => array(false),
|
||||
'use_imap_list_subscribe' => array(true),
|
||||
'use_imap_thread' => array(true),
|
||||
'use_imap_move' => array(true),
|
||||
'use_imap_auth_plain' => array(false),
|
||||
'use_imap_expunge_all_on_delete' => array(false),
|
||||
'imap_forwarded_flag' => array('$Forwarded'),
|
||||
'imap_read_receipt_flag' => array('$ReadReceipt'),
|
||||
'imap_body_text_limit' => array(555000),
|
||||
'imap_message_list_fast_simple_search' => array(true),
|
||||
'imap_message_list_count_limit_trigger' => array(0),
|
||||
'imap_message_list_date_filter' => array(0),
|
||||
'imap_large_thread_limit' => array(100),
|
||||
'imap_folder_list_limit' => array(200),
|
||||
'imap_show_login_alert' => array(true),
|
||||
'smtp_show_server_errors' => array(false),
|
||||
'curl_proxy' => array(''),
|
||||
'curl_proxy_auth' => array(''),
|
||||
'in_iframe' => array(false),
|
||||
'force_https' => array(false),
|
||||
'custom_login_link' => array(''),
|
||||
'custom_logout_link' => array(''),
|
||||
'allow_external_login' => array(false),
|
||||
'allow_external_sso' => array(false),
|
||||
'external_sso_key' => array(''),
|
||||
'fast_cache_memcache_host' => array('127.0.0.1'),
|
||||
'fast_cache_memcache_port' => array(11211),
|
||||
'fast_cache_memcache_expire' => array(43200),
|
||||
'use_local_proxy_for_external_images' => array(false),
|
||||
'dev_email' => array(''),
|
||||
'dev_password' => array('')
|
||||
),
|
||||
|
||||
'version' => array(
|
||||
'current' => array(''),
|
||||
'saved' => array('')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
59
rainloop/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php
Normal file
59
rainloop/v/0.0.0/app/libraries/RainLoop/Config/Plugin.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Config;
|
||||
|
||||
class Plugin extends \RainLoop\Config\AbstractConfig
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aMap;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sPluginName, $aMap = array())
|
||||
{
|
||||
$this->aMap = is_array($aMap) ? $this->convertConfigMap($aMap) : array();
|
||||
|
||||
parent::__construct('plugin-'.$sPluginName.'.ini', '; RainLoop Webmail plugin ('.$sPluginName.')');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aMap
|
||||
* @return array
|
||||
*/
|
||||
private function convertConfigMap($aMap)
|
||||
{
|
||||
if (0 < count($aMap))
|
||||
{
|
||||
$aResultMap = array();
|
||||
foreach ($aMap as /* @var $oProperty \RainLoop\Plugins\Property */ $oProperty)
|
||||
{
|
||||
if ($oProperty)
|
||||
{
|
||||
$mValue = $oProperty->DefaultValue();
|
||||
$sValue = is_array($mValue) && isset($mValue[0]) ? $mValue[0] : $mValue;
|
||||
$aResultMap[$oProperty->Name()] = array($sValue, '');
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < count($aResultMap))
|
||||
{
|
||||
return array(
|
||||
'plugin' => $aResultMap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function defaultValues()
|
||||
{
|
||||
return $this->aMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class Capa
|
||||
{
|
||||
const PREM = 'PREM';
|
||||
const TWO_FACTOR = 'TWO_FACTOR';
|
||||
const OPEN_PGP = 'OPEN_PGP';
|
||||
const PREFETCH = 'PREFETCH';
|
||||
const GRAVATAR = 'GRAVATAR';
|
||||
const THEMES = 'THEMES';
|
||||
const USER_BACKGROUND = 'USER_BACKGROUND';
|
||||
const SIEVE = 'SIEVE';
|
||||
const ATTACHMENT_THUMBNAILS = 'ATTACHMENT_THUMBNAILS';
|
||||
const ADDITIONAL_ACCOUNTS = 'ADDITIONAL_ACCOUNTS';
|
||||
const ADDITIONAL_IDENTITIES = 'ADDITIONAL_IDENTITIES';
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class InterfaceAnimation
|
||||
{
|
||||
const NONE = 'None';
|
||||
const NORMAL = 'Normal';
|
||||
const FULL = 'Full';
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class Layout
|
||||
{
|
||||
const NO_PREVIW = 0;
|
||||
const SIDE_PREVIEW = 1;
|
||||
const BOTTOM_PREVIEW = 2;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class PluginPropertyType
|
||||
{
|
||||
const STRING = 0;
|
||||
const INT = 1;
|
||||
const STRING_TEXT = 2;
|
||||
const PASSWORD = 3;
|
||||
const SELECTION = 4;
|
||||
const BOOL = 5;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class SignMeType
|
||||
{
|
||||
const DEFAILT_OFF = 'DefaultOff';
|
||||
const DEFAILT_ON = 'DefaultOn';
|
||||
const UNUSED = 'Unused';
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class TimeFormat
|
||||
{
|
||||
const F12 = '12';
|
||||
const F24 = '24';
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class UploadClientError
|
||||
{
|
||||
const NORMAL = 0;
|
||||
const FILE_IS_TOO_BIG = 1;
|
||||
const FILE_PARTIALLY_UPLOADED = 2;
|
||||
const FILE_NO_UPLOADED = 3;
|
||||
const MISSING_TEMP_FOLDER = 4;
|
||||
const FILE_ON_SAVING_ERROR = 5;
|
||||
const FILE_TYPE = 98;
|
||||
const UNKNOWN = 99;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Enumerations;
|
||||
|
||||
class UploadError
|
||||
{
|
||||
const UNKNOWN = 1000;
|
||||
const CONFIG_SIZE = 1001;
|
||||
const ON_SAVING = 1002;
|
||||
const EMPTY_FILES_DATA = 1003;
|
||||
const FILE_TYPE = 1004;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Exceptions;
|
||||
|
||||
/**
|
||||
* @category RainLoop
|
||||
* @package Exceptions
|
||||
*/
|
||||
class ClientException extends Exception
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $sAdditionalMessage;
|
||||
|
||||
public function __construct($iCode, $oPrevious = null, $sAdditionalMessage = '')
|
||||
{
|
||||
parent::__construct(\RainLoop\Notifications::GetNotificationsMessage($iCode, $oPrevious),
|
||||
$iCode, $oPrevious);
|
||||
|
||||
$this->sAdditionalMessage = $sAdditionalMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAdditionalMessage()
|
||||
{
|
||||
return $this->sAdditionalMessage;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Exceptions;
|
||||
|
||||
class Exception extends \Exception {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Exceptions;
|
||||
|
||||
/**
|
||||
* @category RainLoop
|
||||
* @package Exceptions
|
||||
*/
|
||||
class InvalidArgumentException extends Exception {}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Exceptions;
|
||||
|
||||
/**
|
||||
* @category RainLoop
|
||||
* @package Exceptions
|
||||
*/
|
||||
class RuntimeException extends Exception {}
|
||||
163
rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php
Normal file
163
rainloop/v/0.0.0/app/libraries/RainLoop/KeyPathHelper.php
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class KeyPathHelper
|
||||
{
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function TwoFactorAuthUserData($sEmail)
|
||||
{
|
||||
return 'TwoFactorAuth/User/'.$sEmail.'/Data/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function WebmailAccounts($sEmail)
|
||||
{
|
||||
return 'Webmail/Accounts/'.$sEmail.'/Array';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function PublicFile($sHash)
|
||||
{
|
||||
return '/Public/Files/'.sha1($sHash).'/Data/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSsoHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function SsoCacherKey($sSsoHash)
|
||||
{
|
||||
return '/Sso/Data/'.$sSsoHash.'/Login/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function RsaCacherKey($sHash)
|
||||
{
|
||||
return '/Rsa/Data/'.$sHash.'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSignMeToken
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function SignMeUserToken($sSignMeToken)
|
||||
{
|
||||
return '/SignMe/UserToken/'.$sSignMeToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDomain
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function LicensingDomainKeyValue($sDomain)
|
||||
{
|
||||
return '/Licensing/DomainKey/Value/'.$sDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDomain
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function LicensingDomainKeyOtherValue($sDomain)
|
||||
{
|
||||
return '/Licensing/DomainKeyOther/Value/'.$sDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRepo
|
||||
* @param string $sRepoFile
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function RepositoryCacheFile($sRepo, $sRepoFile)
|
||||
{
|
||||
return '/RepositoryCache/Repo/'.$sRepo.'/File/'.$sRepoFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRepo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function RepositoryCacheCore($sRepo)
|
||||
{
|
||||
return '/RepositoryCache/CoreRepo/'.$sRepo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sFolderFullName
|
||||
* @param string $sUid
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function ReadReceiptCache($sEmail, $sFolderFullName, $sUid)
|
||||
{
|
||||
return '/ReadReceipt/'.$sEmail.'/'.$sFolderFullName.'/'.$sUid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sLanguage
|
||||
* @param string $sPluginsHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function LangCache($sLanguage, $sPluginsHash)
|
||||
{
|
||||
return '/LangCache/'.$sPluginsHash.'/'.$sLanguage.'/'.APP_VERSION.'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAdmin
|
||||
* @param string $sPluginsHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function TemplatesCache($bAdmin, $sPluginsHash)
|
||||
{
|
||||
return '/TemplatesCache/'.$sPluginsHash.'/'.($bAdmin ? 'Admin' : 'App').'/'.APP_VERSION.'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPluginsHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function PluginsJsCache($sPluginsHash)
|
||||
{
|
||||
return '/PluginsJsCache/'.$sPluginsHash.'/'.APP_VERSION.'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sTheme
|
||||
* @param string $sPluginsHash
|
||||
* @param string $sPublickHash
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function CssCache($sTheme, $sPluginsHash, $sPublickHash = '')
|
||||
{
|
||||
return '/CssCache/'.$sPluginsHash.'/'.$sPublickHash.'/'.$sTheme.'/'.APP_VERSION.'/';
|
||||
}
|
||||
}
|
||||
446
rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php
Normal file
446
rainloop/v/0.0.0/app/libraries/RainLoop/Model/Account.php
Normal file
|
|
@ -0,0 +1,446 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Model;
|
||||
|
||||
class Account extends \RainLoop\Account // for backward compatibility
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sEmail;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sLogin;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $sPassword;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sProxyAuthUser;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sProxyAuthPassword;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sSignMeToken;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Model\Domain
|
||||
*/
|
||||
private $oDomain;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sParentEmail;
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sLogin
|
||||
* @param string $sPassword
|
||||
* @param \RainLoop\Model\Domain $oDomain
|
||||
* @param string $sSignMeToken = ''
|
||||
* @param string $sProxyAuthUser = ''
|
||||
* @param string $sProxyAuthPassword = ''
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function __construct($sEmail, $sLogin, $sPassword, \RainLoop\Model\Domain $oDomain,
|
||||
$sSignMeToken = '', $sProxyAuthUser = '', $sProxyAuthPassword = '')
|
||||
{
|
||||
$this->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
||||
$this->sLogin = \MailSo\Base\Utils::IdnToAscii($sLogin);
|
||||
$this->sPassword = $sPassword;
|
||||
$this->oDomain = $oDomain;
|
||||
$this->sSignMeToken = $sSignMeToken;
|
||||
$this->sProxyAuthUser = $sProxyAuthUser;
|
||||
$this->sProxyAuthPassword = $sProxyAuthPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sLogin
|
||||
* @param string $sPassword
|
||||
* @param \RainLoop\Model\Domain $oDomain
|
||||
* @param string $sSignMeToken = ''
|
||||
* @param string $sProxyAuthUser = ''
|
||||
* @param string $sProxyAuthPassword = ''
|
||||
*
|
||||
* @return \RainLoop\Model\Account
|
||||
*/
|
||||
public static function NewInstance($sEmail, $sLogin, $sPassword, \RainLoop\Model\Domain $oDomain,
|
||||
$sSignMeToken = '', $sProxyAuthUser = '', $sProxyAuthPassword = '')
|
||||
{
|
||||
return new self($sEmail, $sLogin, $sPassword, $oDomain, $sSignMeToken, $sProxyAuthUser, $sProxyAuthPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Email()
|
||||
{
|
||||
return $this->sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ParentEmail()
|
||||
{
|
||||
return $this->sParentEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ProxyAuthUser()
|
||||
{
|
||||
return $this->sProxyAuthUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ProxyAuthPassword()
|
||||
{
|
||||
return $this->sProxyAuthPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ParentEmailHelper()
|
||||
{
|
||||
return 0 < \strlen($this->sParentEmail) ? $this->sParentEmail : $this->sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function IncLogin()
|
||||
{
|
||||
$sLogin = $this->sLogin;
|
||||
if ($this->oDomain->IncShortLogin())
|
||||
{
|
||||
$sLogin = \MailSo\Base\Utils::GetAccountNameFromEmail($this->sLogin);
|
||||
}
|
||||
|
||||
return $sLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function IncPassword()
|
||||
{
|
||||
return $this->sPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function OutLogin()
|
||||
{
|
||||
$sLogin = $this->sLogin;
|
||||
if ($this->oDomain->OutShortLogin())
|
||||
{
|
||||
$sLogin = \MailSo\Base\Utils::GetAccountNameFromEmail($this->sLogin);
|
||||
}
|
||||
|
||||
return $sLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Login()
|
||||
{
|
||||
return $this->IncLogin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Password()
|
||||
{
|
||||
return $this->IncPassword();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function SignMe()
|
||||
{
|
||||
return 0 < \strlen($this->sSignMeToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function SignMeToken()
|
||||
{
|
||||
return $this->sSignMeToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Model\Domain
|
||||
*/
|
||||
public function Domain()
|
||||
{
|
||||
return $this->oDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Hash()
|
||||
{
|
||||
return md5(APP_SALT.$this->Email().APP_SALT.$this->DomainIncHost().
|
||||
APP_SALT.$this->DomainIncPort().APP_SALT.$this->Password().APP_SALT.'0'.APP_SALT.$this->ParentEmail().APP_SALT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPassword
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function SetPassword($sPassword)
|
||||
{
|
||||
$this->sPassword = $sPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sParentEmail
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function SetParentEmail($sParentEmail)
|
||||
{
|
||||
$this->sParentEmail = \MailSo\Base\Utils::IdnToAscii($sParentEmail, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sProxyAuthUser
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function SetProxyAuthUser($sProxyAuthUser)
|
||||
{
|
||||
return $this->sProxyAuthUser = $sProxyAuthUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sProxyAuthPassword
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function SetProxyAuthPassword($sProxyAuthPassword)
|
||||
{
|
||||
return $this->sProxyAuthPassword = $sProxyAuthPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function DomainIncHost()
|
||||
{
|
||||
return $this->Domain()->IncHost();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function DomainIncPort()
|
||||
{
|
||||
return $this->Domain()->IncPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function DomainIncSecure()
|
||||
{
|
||||
return $this->Domain()->IncSecure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function DomainOutHost()
|
||||
{
|
||||
return $this->Domain()->OutHost();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function DomainOutPort()
|
||||
{
|
||||
return $this->Domain()->OutPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function DomainOutSecure()
|
||||
{
|
||||
return $this->Domain()->OutSecure();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function DomainOutAuth()
|
||||
{
|
||||
return $this->Domain()->OutAuth();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetAuthToken()
|
||||
{
|
||||
return \RainLoop\Utils::EncodeKeyValues(array(
|
||||
'token', // 0
|
||||
$this->sEmail, // 1
|
||||
$this->sLogin, // 2
|
||||
$this->sPassword, // 3
|
||||
\RainLoop\Utils::Fingerprint(), // 4
|
||||
$this->sSignMeToken, // 5
|
||||
$this->sParentEmail, // 6
|
||||
\RainLoop\Utils::GetShortToken(), // 7
|
||||
$this->sProxyAuthUser, // 8
|
||||
$this->sProxyAuthPassword, // 9
|
||||
0 // 10
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Plugins\Manager $oPlugins
|
||||
* @param \MailSo\Mail\MailClient $oMailClient
|
||||
* @param \RainLoop\Application $oConfig
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IncConnectAndLoginHelper($oPlugins, $oMailClient, $oConfig)
|
||||
{
|
||||
$bLogin = false;
|
||||
|
||||
$aImapCredentials = array(
|
||||
'UseConnect' => true,
|
||||
'UseAuth' => true,
|
||||
'Host' => $this->DomainIncHost(),
|
||||
'Port' => $this->DomainIncPort(),
|
||||
'Secure' => $this->DomainIncSecure(),
|
||||
'Login' => $this->IncLogin(),
|
||||
'Password' => $this->Password(),
|
||||
'ProxyAuthUser' => $this->ProxyAuthUser(),
|
||||
'ProxyAuthPassword' => $this->ProxyAuthPassword(),
|
||||
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false),
|
||||
'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true),
|
||||
'UseAuthPlainIfSupported' => !!$oConfig->Get('labs', 'use_imap_auth_plain')
|
||||
);
|
||||
|
||||
$oPlugins->RunHook('filter.imap-credentials', array($this, &$aImapCredentials));
|
||||
|
||||
$oPlugins->RunHook('event.imap-pre-connect', array($this, $aImapCredentials['UseConnect'], $aImapCredentials));
|
||||
|
||||
if ($aImapCredentials['UseConnect'])
|
||||
{
|
||||
$oMailClient
|
||||
->Connect($aImapCredentials['Host'], $aImapCredentials['Port'],
|
||||
$aImapCredentials['Secure'], $aImapCredentials['VerifySsl'], $aImapCredentials['AllowSelfSigned']);
|
||||
|
||||
}
|
||||
|
||||
$oPlugins->RunHook('event.imap-pre-login', array($this, $aImapCredentials['UseAuth'], $aImapCredentials));
|
||||
|
||||
if ($aImapCredentials['UseAuth'])
|
||||
{
|
||||
if (0 < \strlen($aImapCredentials['ProxyAuthUser']) &&
|
||||
0 < \strlen($aImapCredentials['ProxyAuthPassword']))
|
||||
{
|
||||
$oMailClient
|
||||
->Login($aImapCredentials['ProxyAuthUser'], $aImapCredentials['ProxyAuthPassword'],
|
||||
$aImapCredentials['Login'], $aImapCredentials['UseAuthPlainIfSupported']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oMailClient->Login($aImapCredentials['Login'], $aImapCredentials['Password'], '',
|
||||
$aImapCredentials['UseAuthPlainIfSupported']);
|
||||
}
|
||||
|
||||
$bLogin = true;
|
||||
}
|
||||
|
||||
$oPlugins->RunHook('event.imap-post-login', array($this, $aImapCredentials['UseAuth'], $bLogin, $aImapCredentials));
|
||||
|
||||
return $bLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Plugins\Manager $oPlugins
|
||||
* @param \MailSo\Smtp\SmtpClient|null $oSmtpClient
|
||||
* @param \RainLoop\Application $oConfig
|
||||
* @param bool $bUsePhpMail = false
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function OutConnectAndLoginHelper($oPlugins, $oSmtpClient, $oConfig, &$bUsePhpMail = false)
|
||||
{
|
||||
$bLogin = false;
|
||||
|
||||
$aSmtpCredentials = array(
|
||||
'UseConnect' => true,
|
||||
'UseAuth' => $this->DomainOutAuth(),
|
||||
'UsePhpMail' => $bUsePhpMail,
|
||||
'Ehlo' => \MailSo\Smtp\SmtpClient::EhloHelper(),
|
||||
'Host' => $this->DomainOutHost(),
|
||||
'Port' => $this->DomainOutPort(),
|
||||
'Secure' => $this->DomainOutSecure(),
|
||||
'Login' => $this->OutLogin(),
|
||||
'Password' => $this->Password(),
|
||||
'ProxyAuthUser' => $this->ProxyAuthUser(),
|
||||
'ProxyAuthPassword' => $this->ProxyAuthPassword(),
|
||||
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false),
|
||||
'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true)
|
||||
);
|
||||
|
||||
$oPlugins->RunHook('filter.smtp-credentials', array($this, &$aSmtpCredentials));
|
||||
|
||||
$bUsePhpMail = $aSmtpCredentials['UsePhpMail'];
|
||||
|
||||
$oPlugins->RunHook('event.smtp-pre-connect', array($this, $aSmtpCredentials['UseConnect'], $aSmtpCredentials));
|
||||
|
||||
if ($aSmtpCredentials['UseConnect'] && !$aSmtpCredentials['UsePhpMail'] && $oSmtpClient)
|
||||
{
|
||||
$oSmtpClient->Connect($aSmtpCredentials['Host'], $aSmtpCredentials['Port'], $aSmtpCredentials['Ehlo'],
|
||||
$aSmtpCredentials['Secure'], $aSmtpCredentials['VerifySsl'], $aSmtpCredentials['AllowSelfSigned']
|
||||
);
|
||||
}
|
||||
|
||||
$oPlugins->RunHook('event.smtp-post-connect', array($this, $aSmtpCredentials['UseConnect'], $aSmtpCredentials));
|
||||
$oPlugins->RunHook('event.smtp-pre-login', array($this, $aSmtpCredentials['UseAuth'], $aSmtpCredentials));
|
||||
|
||||
if ($aSmtpCredentials['UseAuth'] && !$aSmtpCredentials['UsePhpMail'] && $oSmtpClient)
|
||||
{
|
||||
$oSmtpClient->Login($aSmtpCredentials['Login'], $aSmtpCredentials['Password']);
|
||||
|
||||
$bLogin = true;
|
||||
}
|
||||
|
||||
$oPlugins->RunHook('event.smtp-post-login', array($this, $aSmtpCredentials['UseAuth'], $bLogin, $aSmtpCredentials));
|
||||
|
||||
return $bLogin;
|
||||
}
|
||||
}
|
||||
536
rainloop/v/0.0.0/app/libraries/RainLoop/Model/Domain.php
Normal file
536
rainloop/v/0.0.0/app/libraries/RainLoop/Model/Domain.php
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Model;
|
||||
|
||||
use MailSo\Net\Enumerations\ConnectionSecurityType;
|
||||
|
||||
class Domain
|
||||
{
|
||||
const DEFAULT_FORWARDED_FLAG = '$Forwarded';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sIncHost;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iIncPort;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iIncSecure;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bIncShortLogin;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sOutHost;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iOutPort;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iOutSecure;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bOutShortLogin;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bOutAuth;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bOutUsePhpMail;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bUseSieve;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sSieveHost;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iSievePort;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iSieveSecure;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sWhiteList;
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sIncHost
|
||||
* @param int $iIncPort
|
||||
* @param int $iIncSecure
|
||||
* @param bool $bIncShortLogin
|
||||
* @param bool $bUseSieve
|
||||
* @param string $sSieveHost
|
||||
* @param int $iSievePort
|
||||
* @param int $iSieveSecure
|
||||
* @param string $sOutHost
|
||||
* @param int $iOutPort
|
||||
* @param int $iOutSecure
|
||||
* @param bool $bOutShortLogin
|
||||
* @param bool $bOutAuth
|
||||
* @param bool $bOutUsePhpMail = false
|
||||
* @param string $sWhiteList = ''
|
||||
*/
|
||||
private function __construct($sName,
|
||||
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
|
||||
$bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
|
||||
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail = false,
|
||||
$sWhiteList = '')
|
||||
{
|
||||
$this->sName = $sName;
|
||||
$this->sIncHost = $sIncHost;
|
||||
$this->iIncPort = $iIncPort;
|
||||
$this->iIncSecure = $iIncSecure;
|
||||
$this->bIncShortLogin = $bIncShortLogin;
|
||||
|
||||
$this->sOutHost = $sOutHost;
|
||||
$this->iOutPort = $iOutPort;
|
||||
$this->iOutSecure = $iOutSecure;
|
||||
$this->bOutShortLogin = $bOutShortLogin;
|
||||
$this->bOutAuth = $bOutAuth;
|
||||
$this->bOutUsePhpMail = $bOutUsePhpMail;
|
||||
|
||||
$this->bUseSieve = $bUseSieve;
|
||||
$this->sSieveHost = $sSieveHost;
|
||||
$this->iSievePort = $iSievePort;
|
||||
$this->iSieveSecure = $iSieveSecure;
|
||||
|
||||
$this->sWhiteList = \trim($sWhiteList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sIncHost
|
||||
* @param int $iIncPort
|
||||
* @param int $iIncSecure
|
||||
* @param bool $bIncShortLogin
|
||||
* @param bool $bUseSieve
|
||||
* @param string $sSieveHost
|
||||
* @param int $iSievePort
|
||||
* @param int $iSieveSecure
|
||||
* @param string $sOutHost
|
||||
* @param int $iOutPort
|
||||
* @param int $iOutSecure
|
||||
* @param bool $bOutShortLogin
|
||||
* @param bool $bOutAuth
|
||||
* @param bool $bOutUsePhpMail = false
|
||||
* @param string $sWhiteList = ''
|
||||
*
|
||||
* @return \RainLoop\Model\Domain
|
||||
*/
|
||||
public static function NewInstance($sName,
|
||||
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
|
||||
$bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
|
||||
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
|
||||
$sWhiteList = '')
|
||||
{
|
||||
return new self($sName,
|
||||
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
|
||||
$bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
|
||||
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
|
||||
$sWhiteList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param array $aDomain
|
||||
*
|
||||
* @return \RainLoop\Model\Domain|null
|
||||
*/
|
||||
public static function NewInstanceFromDomainConfigArray($sName, $aDomain)
|
||||
{
|
||||
$oDomain = null;
|
||||
|
||||
if (0 < \strlen($sName) && \is_array($aDomain) && 0 < \strlen($aDomain['imap_host']) && 0 < \strlen($aDomain['imap_port']))
|
||||
{
|
||||
$sIncHost = (string) $aDomain['imap_host'];
|
||||
$iIncPort = (int) $aDomain['imap_port'];
|
||||
$iIncSecure = self::StrConnectionSecurityTypeToCons(
|
||||
!empty($aDomain['imap_secure']) ? $aDomain['imap_secure'] : '');
|
||||
|
||||
$bUseSieve = isset($aDomain['sieve_use']) ? (bool) $aDomain['sieve_use'] : false;
|
||||
|
||||
$sSieveHost = empty($aDomain['sieve_host']) ? '' : (string) $aDomain['sieve_host'];
|
||||
$iSievePort = empty($aDomain['sieve_port']) ? 2000 : (int) $aDomain['sieve_port'];
|
||||
$iSieveSecure = self::StrConnectionSecurityTypeToCons(
|
||||
!empty($aDomain['sieve_secure']) ? $aDomain['sieve_secure'] : '');
|
||||
|
||||
$sOutHost = empty($aDomain['smtp_host']) ? '' : (string) $aDomain['smtp_host'];
|
||||
$iOutPort = empty($aDomain['smtp_port']) ? 25 : (int) $aDomain['smtp_port'];
|
||||
$iOutSecure = self::StrConnectionSecurityTypeToCons(
|
||||
!empty($aDomain['smtp_secure']) ? $aDomain['smtp_secure'] : '');
|
||||
|
||||
$bOutAuth = isset($aDomain['smtp_auth']) ? (bool) $aDomain['smtp_auth'] : true;
|
||||
$bOutUsePhpMail = isset($aDomain['smtp_php_mail']) ? (bool) $aDomain['smtp_php_mail'] : false;
|
||||
$sWhiteList = (string) (isset($aDomain['white_list']) ? $aDomain['white_list'] : '');
|
||||
|
||||
$bIncShortLogin = isset($aDomain['imap_short_login']) ? (bool) $aDomain['imap_short_login'] : false;
|
||||
$bOutShortLogin = isset($aDomain['smtp_short_login']) ? (bool) $aDomain['smtp_short_login'] : false;
|
||||
|
||||
$oDomain = self::NewInstance($sName,
|
||||
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
|
||||
$bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
|
||||
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
|
||||
$sWhiteList);
|
||||
}
|
||||
|
||||
return $oDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sStr
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function encodeIniString($sStr)
|
||||
{
|
||||
return str_replace('"', '\\"', $sStr);
|
||||
}
|
||||
|
||||
public function Normalize()
|
||||
{
|
||||
$this->sIncHost = \trim($this->sIncHost);
|
||||
$this->sSieveHost = \trim($this->sSieveHost);
|
||||
$this->sOutHost = \trim($this->sOutHost);
|
||||
$this->sWhiteList = \trim($this->sWhiteList);
|
||||
|
||||
if ($this->iIncPort <= 0)
|
||||
{
|
||||
$this->iIncPort = 143;
|
||||
}
|
||||
|
||||
if ($this->iSievePort <= 0)
|
||||
{
|
||||
$this->iSievePort = 2000;
|
||||
}
|
||||
|
||||
if ($this->iOutPort <= 0)
|
||||
{
|
||||
$this->iOutPort = 25;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ToIniString()
|
||||
{
|
||||
$this->Normalize();
|
||||
return \implode("\n", array(
|
||||
'imap_host = "'.$this->encodeIniString($this->sIncHost).'"',
|
||||
'imap_port = '.$this->iIncPort,
|
||||
'imap_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iIncSecure).'"',
|
||||
'imap_short_login = '.($this->bIncShortLogin ? 'On' : 'Off'),
|
||||
'sieve_use = '.($this->bUseSieve ? 'On' : 'Off'),
|
||||
'sieve_host = "'.$this->encodeIniString($this->sSieveHost).'"',
|
||||
'sieve_port = '.$this->iSievePort,
|
||||
'sieve_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iSieveSecure).'"',
|
||||
'smtp_host = "'.$this->encodeIniString($this->sOutHost).'"',
|
||||
'smtp_port = '.$this->iOutPort,
|
||||
'smtp_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iOutSecure).'"',
|
||||
'smtp_short_login = '.($this->bOutShortLogin ? 'On' : 'Off'),
|
||||
'smtp_auth = '.($this->bOutAuth ? 'On' : 'Off'),
|
||||
'smtp_php_mail = '.($this->bOutUsePhpMail ? 'On' : 'Off'),
|
||||
'white_list = "'.$this->encodeIniString($this->sWhiteList).'"'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sType
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function StrConnectionSecurityTypeToCons($sType)
|
||||
{
|
||||
$iSecurityType = ConnectionSecurityType::NONE;
|
||||
switch (strtoupper($sType))
|
||||
{
|
||||
case 'SSL':
|
||||
$iSecurityType = ConnectionSecurityType::SSL;
|
||||
break;
|
||||
case 'TLS':
|
||||
$iSecurityType = ConnectionSecurityType::STARTTLS;
|
||||
break;
|
||||
}
|
||||
return $iSecurityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iSecurityType
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function ConstConnectionSecurityTypeToStr($iSecurityType)
|
||||
{
|
||||
$sType = 'None';
|
||||
switch ($iSecurityType)
|
||||
{
|
||||
case ConnectionSecurityType::SSL:
|
||||
$sType = 'SSL';
|
||||
break;
|
||||
case ConnectionSecurityType::STARTTLS:
|
||||
$sType = 'TLS';
|
||||
break;
|
||||
}
|
||||
|
||||
return $sType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sIncHost
|
||||
* @param int $iIncPort
|
||||
* @param int $iIncSecure
|
||||
* @param bool $bIncShortLogin
|
||||
* @param bool $bUseSieve
|
||||
* @param string $sOutHost
|
||||
* @param int $iOutPort
|
||||
* @param int $iOutSecure
|
||||
* @param bool $bOutShortLogin
|
||||
* @param bool $bOutAuth
|
||||
* @param bool $bOutUsePhpMail = false
|
||||
* @param string $sWhiteList = ''
|
||||
*
|
||||
* @return \RainLoop\Model\Domain
|
||||
*/
|
||||
public function UpdateInstance(
|
||||
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
|
||||
$bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
|
||||
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
|
||||
$sWhiteList = '')
|
||||
{
|
||||
$this->sIncHost = \MailSo\Base\Utils::IdnToAscii($sIncHost);
|
||||
$this->iIncPort = $iIncPort;
|
||||
$this->iIncSecure = $iIncSecure;
|
||||
$this->bIncShortLogin = $bIncShortLogin;
|
||||
|
||||
$this->bUseSieve = $bUseSieve;
|
||||
$this->sSieveHost = \MailSo\Base\Utils::IdnToAscii($sSieveHost);
|
||||
$this->iSievePort = $iSievePort;
|
||||
$this->iSieveSecure = $iSieveSecure;
|
||||
|
||||
$this->sOutHost = \MailSo\Base\Utils::IdnToAscii($sOutHost);
|
||||
$this->iOutPort = $iOutPort;
|
||||
$this->iOutSecure = $iOutSecure;
|
||||
$this->bOutShortLogin = $bOutShortLogin;
|
||||
$this->bOutAuth = $bOutAuth;
|
||||
$this->bOutUsePhpMail = $bOutUsePhpMail;
|
||||
|
||||
$this->sWhiteList = \trim($sWhiteList);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Name()
|
||||
{
|
||||
return $this->sName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function IncHost()
|
||||
{
|
||||
return $this->sIncHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function IncPort()
|
||||
{
|
||||
return $this->iIncPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function IncSecure()
|
||||
{
|
||||
return $this->iIncSecure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IncShortLogin()
|
||||
{
|
||||
return $this->bIncShortLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function UseSieve()
|
||||
{
|
||||
return $this->bUseSieve;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function SieveHost()
|
||||
{
|
||||
return $this->sSieveHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function SievePort()
|
||||
{
|
||||
return $this->iSievePort;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function SieveSecure()
|
||||
{
|
||||
return $this->iSieveSecure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function OutHost()
|
||||
{
|
||||
return $this->sOutHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function OutPort()
|
||||
{
|
||||
return $this->iOutPort;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function OutSecure()
|
||||
{
|
||||
return $this->iOutSecure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function OutShortLogin()
|
||||
{
|
||||
return $this->bOutShortLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function OutAuth()
|
||||
{
|
||||
return $this->bOutAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function OutUsePhpMail()
|
||||
{
|
||||
return $this->bOutUsePhpMail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function WhiteList()
|
||||
{
|
||||
return $this->sWhiteList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sLogin = ''
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ValidateWhiteList($sEmail, $sLogin = '')
|
||||
{
|
||||
$sW = \trim($this->sWhiteList);
|
||||
if (0 < strlen($sW))
|
||||
{
|
||||
$sEmail = \MailSo\Base\Utils::IdnToUtf8($sEmail, true);
|
||||
$sLogin = \MailSo\Base\Utils::IdnToUtf8($sLogin);
|
||||
|
||||
$sW = \preg_replace('/([^\s]+)@[^\s]*/', '$1', $sW);
|
||||
$sW = ' '.\trim(\preg_replace('/[\s;,\r\n\t]+/', ' ', $sW)).' ';
|
||||
|
||||
$sUserPart = \MailSo\Base\Utils::GetAccountNameFromEmail(0 < \strlen($sLogin) ? $sLogin : $sEmail);
|
||||
return false !== \strpos($sW, ' '.$sUserPart.' ');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAjax = false
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ToSimpleJSON($bAjax = false)
|
||||
{
|
||||
return array(
|
||||
'Name' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->Name()) : $this->Name(),
|
||||
'IncHost' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->IncHost()) : $this->IncHost(),
|
||||
'IncPort' => $this->IncPort(),
|
||||
'IncSecure' => $this->IncSecure(),
|
||||
'IncShortLogin' => $this->IncShortLogin(),
|
||||
'UseSieve' => $this->UseSieve(),
|
||||
'SieveHost' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->SieveHost()) : $this->SieveHost(),
|
||||
'SievePort' => $this->SievePort(),
|
||||
'SieveSecure' => $this->SieveSecure(),
|
||||
'OutHost' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->OutHost()) : $this->OutHost(),
|
||||
'OutPort' => $this->OutPort(),
|
||||
'OutSecure' => $this->OutSecure(),
|
||||
'OutShortLogin' => $this->OutShortLogin(),
|
||||
'OutAuth' => $this->OutAuth(),
|
||||
'OutUsePhpMail' => $this->OutUsePhpMail(),
|
||||
'WhiteList' => $this->WhiteList()
|
||||
);
|
||||
}
|
||||
}
|
||||
179
rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php
Normal file
179
rainloop/v/0.0.0/app/libraries/RainLoop/Model/Identity.php
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Model;
|
||||
|
||||
class Identity
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sEmail;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sReplyTo;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sBcc;
|
||||
|
||||
/**
|
||||
* @param string $sId
|
||||
* @param string $sEmail
|
||||
* @param string $sName
|
||||
* @param string $sReplyTo
|
||||
* @param string $sBcc
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function __construct($sId, $sEmail, $sName, $sReplyTo, $sBcc)
|
||||
{
|
||||
$this->sId = $sId;
|
||||
$this->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
||||
$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\Model\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\Model\Identity
|
||||
*/
|
||||
public function SetId($sId)
|
||||
{
|
||||
$this->sId = $sId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Email()
|
||||
{
|
||||
return $this->sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return \RainLoop\Model\Identity
|
||||
*/
|
||||
public function SetEmail($sEmail)
|
||||
{
|
||||
$this->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Name()
|
||||
{
|
||||
return $this->sName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return \RainLoop\Model\Identity
|
||||
*/
|
||||
public function SetName($sName)
|
||||
{
|
||||
$this->sName = $sName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ReplyTo()
|
||||
{
|
||||
return $this->sReplyTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sReplyTo
|
||||
*
|
||||
* @return \RainLoop\Model\Identity
|
||||
*/
|
||||
public function SetReplyTo($sReplyTo)
|
||||
{
|
||||
$this->sReplyTo = $sReplyTo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Bcc()
|
||||
{
|
||||
return $this->sBcc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sBcc
|
||||
*
|
||||
* @return \RainLoop\Model\Identity
|
||||
*/
|
||||
public function SetBcc($sBcc)
|
||||
{
|
||||
$this->sBcc = $sBcc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAjax = false
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ToSimpleJSON($bAjax = false)
|
||||
{
|
||||
return array(
|
||||
'Id' => $this->Id(),
|
||||
'Email' => $bAjax ? \MailSo\Base\Utils::IdnToUtf8($this->Email()) : $this->Email(),
|
||||
'Name' => $this->Name(),
|
||||
'ReplyTo' => $this->ReplyTo(),
|
||||
'Bcc' => $this->Bcc()
|
||||
);
|
||||
}
|
||||
}
|
||||
143
rainloop/v/0.0.0/app/libraries/RainLoop/Notifications.php
Normal file
143
rainloop/v/0.0.0/app/libraries/RainLoop/Notifications.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Notifications
|
||||
{
|
||||
const InvalidToken = 101;
|
||||
const AuthError = 102;
|
||||
const AccessError = 103;
|
||||
const ConnectionError = 104;
|
||||
const CaptchaError = 105;
|
||||
const SocialFacebookLoginAccessDisable = 106;
|
||||
const SocialTwitterLoginAccessDisable = 107;
|
||||
const SocialGoogleLoginAccessDisable = 108;
|
||||
const DomainNotAllowed = 109;
|
||||
const AccountNotAllowed = 110;
|
||||
|
||||
const AccountTwoFactorAuthRequired = 120;
|
||||
const AccountTwoFactorAuthError = 121;
|
||||
|
||||
const CouldNotSaveNewPassword = 130;
|
||||
const CurrentPasswordIncorrect = 131;
|
||||
const NewPasswordShort = 132;
|
||||
const NewPasswordWeak = 133;
|
||||
const NewPasswordForbidden = 134;
|
||||
|
||||
const ContactsSyncError = 140;
|
||||
|
||||
const CantGetMessageList = 201;
|
||||
const CantGetMessage = 202;
|
||||
const CantDeleteMessage = 203;
|
||||
const CantMoveMessage = 204;
|
||||
const CantCopyMessage = 205;
|
||||
|
||||
const CantSaveMessage = 301;
|
||||
const CantSendMessage = 302;
|
||||
const InvalidRecipients = 303;
|
||||
|
||||
const CantCreateFolder = 400;
|
||||
const CantRenameFolder = 401;
|
||||
const CantDeleteFolder = 402;
|
||||
const CantSubscribeFolder = 403;
|
||||
const CantUnsubscribeFolder = 404;
|
||||
const CantDeleteNonEmptyFolder = 405;
|
||||
|
||||
const CantSaveSettings = 501;
|
||||
const CantSavePluginSettings = 502;
|
||||
|
||||
const DomainAlreadyExists = 601;
|
||||
|
||||
const CantInstallPackage = 701;
|
||||
const CantDeletePackage = 702;
|
||||
const InvalidPluginPackage = 703;
|
||||
const UnsupportedPluginPackage = 704;
|
||||
|
||||
const LicensingServerIsUnavailable = 710;
|
||||
const LicensingExpired = 711;
|
||||
const LicensingBanned = 712;
|
||||
|
||||
const DemoSendMessageError = 750;
|
||||
|
||||
const AccountAlreadyExists = 801;
|
||||
const AccountDoesNotExist = 802;
|
||||
|
||||
const MailServerError = 901;
|
||||
const ClientViewError = 902;
|
||||
const InvalidInputArgument = 903;
|
||||
const UnknownNotification = 998;
|
||||
const UnknownError = 999;
|
||||
|
||||
/**
|
||||
* @staticvar array $aMap
|
||||
*
|
||||
* @param int $iCode
|
||||
* @param \Exception|null $oPrevious
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function GetNotificationsMessage($iCode, $oPrevious = null)
|
||||
{
|
||||
static $aMap = array(
|
||||
self::InvalidToken => 'InvalidToken',
|
||||
self::AuthError => 'AuthError',
|
||||
self::AccessError => 'AccessError',
|
||||
self::ConnectionError => 'ConnectionError',
|
||||
self::CaptchaError => 'CaptchaError',
|
||||
self::SocialFacebookLoginAccessDisable => 'SocialFacebookLoginAccessDisable',
|
||||
self::SocialTwitterLoginAccessDisable => 'SocialTwitterLoginAccessDisable',
|
||||
self::SocialGoogleLoginAccessDisable => 'SocialGoogleLoginAccessDisable',
|
||||
self::DomainNotAllowed => 'DomainNotAllowed',
|
||||
self::AccountNotAllowed => 'AccountNotAllowed',
|
||||
self::AccountTwoFactorAuthRequired => 'AccountTwoFactorAuthRequired',
|
||||
self::AccountTwoFactorAuthError => 'AccountTwoFactorAuthError',
|
||||
|
||||
self::CouldNotSaveNewPassword => 'CouldNotSaveNewPassword',
|
||||
self::CurrentPasswordIncorrect => 'CurrentPasswordIncorrect',
|
||||
self::NewPasswordShort => 'NewPasswordShort',
|
||||
self::NewPasswordWeak => 'NewPasswordWeak',
|
||||
self::NewPasswordForbidden => 'NewPasswordForbidden',
|
||||
|
||||
self::ContactsSyncError => 'ContactsSyncError',
|
||||
|
||||
self::CantGetMessageList => 'CantGetMessageList',
|
||||
self::CantGetMessage => 'CantGetMessage',
|
||||
self::CantDeleteMessage => 'CantDeleteMessage',
|
||||
self::CantMoveMessage => 'CantMoveMessage',
|
||||
self::CantSaveMessage => 'CantSaveMessage',
|
||||
self::CantSendMessage => 'CantSendMessage',
|
||||
self::InvalidRecipients => 'InvalidRecipients',
|
||||
self::CantCreateFolder => 'CantCreateFolder',
|
||||
self::CantRenameFolder => 'CantRenameFolder',
|
||||
self::CantDeleteFolder => 'CantDeleteFolder',
|
||||
self::CantSubscribeFolder => 'CantSubscribeFolder',
|
||||
self::CantUnsubscribeFolder => 'CantUnsubscribeFolder',
|
||||
self::CantDeleteNonEmptyFolder => 'CantDeleteNonEmptyFolder',
|
||||
self::CantSaveSettings => 'CantSaveSettings',
|
||||
self::CantSavePluginSettings => 'CantSavePluginSettings',
|
||||
self::DomainAlreadyExists => 'DomainAlreadyExists',
|
||||
self::CantInstallPackage => 'CantInstallPackage',
|
||||
self::CantDeletePackage => 'CantDeletePackage',
|
||||
self::InvalidPluginPackage => 'InvalidPluginPackage',
|
||||
self::UnsupportedPluginPackage => 'UnsupportedPluginPackage',
|
||||
self::LicensingServerIsUnavailable => 'LicensingServerIsUnavailable',
|
||||
self::LicensingExpired => 'LicensingExpired',
|
||||
self::LicensingBanned => 'LicensingBanned',
|
||||
self::DemoSendMessageError => 'DemoSendMessageError',
|
||||
self::AccountAlreadyExists => 'AccountAlreadyExists',
|
||||
self::AccountDoesNotExist => 'AccountDoesNotExist',
|
||||
self::MailServerError => 'MailServerError',
|
||||
self::ClientViewError => 'ClientViewError',
|
||||
self::InvalidInputArgument => 'InvalidInputArgument',
|
||||
self::UnknownNotification => 'UnknownNotification',
|
||||
self::UnknownError => 'UnknownError'
|
||||
);
|
||||
|
||||
if (self::ClientViewError === $iCode && $oPrevious instanceof \Exception)
|
||||
{
|
||||
return $oPrevious->getMessage();
|
||||
}
|
||||
|
||||
return isset($aMap[$iCode]) ? $aMap[$iCode].'['.$iCode.']' : 'UnknownNotification['.$iCode.']';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Plugins;
|
||||
|
||||
abstract class AbstractPlugin
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Plugins\Manager
|
||||
*/
|
||||
private $oPluginManager;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Config\Plugin
|
||||
*/
|
||||
private $oPluginConfig;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bLangs;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sPath;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sVersion;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aConfigMap;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bPluginConfigLoaded;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->sName = '';
|
||||
$this->sPath = '';
|
||||
$this->sVersion = '0.0';
|
||||
$this->aConfigMap = null;
|
||||
|
||||
$this->oPluginManager = null;
|
||||
$this->oPluginConfig = null;
|
||||
$this->bPluginConfigLoaded = false;
|
||||
$this->bLangs = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Config\Plugin
|
||||
*/
|
||||
public function Config()
|
||||
{
|
||||
if (!$this->bPluginConfigLoaded && $this->oPluginConfig)
|
||||
{
|
||||
$this->bPluginConfigLoaded = true;
|
||||
if ($this->oPluginConfig->IsInited())
|
||||
{
|
||||
if (!$this->oPluginConfig->Load())
|
||||
{
|
||||
$this->oPluginConfig->Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->oPluginConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function Manager()
|
||||
{
|
||||
return $this->oPluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Path()
|
||||
{
|
||||
return $this->sPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Name()
|
||||
{
|
||||
return $this->sName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Version()
|
||||
{
|
||||
return $this->sVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool | null $bLangs = null
|
||||
* @return bool
|
||||
*/
|
||||
public function UseLangs($bLangs = null)
|
||||
{
|
||||
if (null !== $bLangs)
|
||||
{
|
||||
$this->bLangs = (bool) $bLangs;
|
||||
}
|
||||
|
||||
return $this->bLangs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
protected function configMapping()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Hash()
|
||||
{
|
||||
return \md5($this->sName.'@'.$this->sVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Supported()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @final
|
||||
* @return array
|
||||
*/
|
||||
final public function ConfigMap()
|
||||
{
|
||||
if (null === $this->aConfigMap)
|
||||
{
|
||||
$this->aConfigMap = $this->configMapping();
|
||||
if (!is_array($this->aConfigMap))
|
||||
{
|
||||
$this->aConfigMap = array();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->aConfigMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPath
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function SetPath($sPath)
|
||||
{
|
||||
$this->sPath = $sPath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function SetName($sName)
|
||||
{
|
||||
$this->sName = $sName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sVersion
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function SetVersion($sVersion)
|
||||
{
|
||||
if (0 < \strlen($sVersion))
|
||||
{
|
||||
$this->sVersion = $sVersion;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Plugins\Manager $oPluginManager
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function SetPluginManager(\RainLoop\Plugins\Manager $oPluginManager)
|
||||
{
|
||||
$this->oPluginManager = $oPluginManager;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Config\Plugin $oPluginConfig
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function SetPluginConfig(\RainLoop\Config\Plugin $oPluginConfig)
|
||||
{
|
||||
$this->oPluginConfig = $oPluginConfig;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function PreInit()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAdmin
|
||||
* @param bool $bAuth
|
||||
* @param array $aConfig
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function FilterAppDataPluginSection($bAdmin, $bAuth, &$aConfig)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHookName
|
||||
* @param string $sFunctionName
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function addHook($sHookName, $sFunctionName)
|
||||
{
|
||||
if ($this->oPluginManager)
|
||||
{
|
||||
$this->oPluginManager->AddHook($sHookName, array(&$this, $sFunctionName));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFile
|
||||
* @param bool $bAdminScope = false
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function addJs($sFile, $bAdminScope = false)
|
||||
{
|
||||
if ($this->oPluginManager)
|
||||
{
|
||||
$this->oPluginManager->AddJs($this->sPath.'/'.$sFile, $bAdminScope);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFile
|
||||
* @param bool $bAdminScope = false
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function addTemplate($sFile, $bAdminScope = false)
|
||||
{
|
||||
if ($this->oPluginManager)
|
||||
{
|
||||
$this->oPluginManager->AddTemplate($this->sPath.'/'.$sFile, $bAdminScope);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sActionName
|
||||
* @param string $sFunctionName
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function addPartHook($sActionName, $sFunctionName)
|
||||
{
|
||||
if ($this->oPluginManager)
|
||||
{
|
||||
$this->oPluginManager->AddAdditionalPartAction($sActionName, array(&$this, $sFunctionName));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sActionName
|
||||
* @param string $sFunctionName
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function addAjaxHook($sActionName, $sFunctionName)
|
||||
{
|
||||
if ($this->oPluginManager)
|
||||
{
|
||||
$this->oPluginManager->AddAdditionalAjaxAction($sActionName, array(&$this, $sFunctionName));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sPlace
|
||||
* @param string $sHtml
|
||||
* @param bool $bPrepend = false
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function addTemplateHook($sName, $sPlace, $sLocalTemplateName, $bPrepend = false)
|
||||
{
|
||||
if ($this->oPluginManager)
|
||||
{
|
||||
$this->oPluginManager->AddProcessTemplateAction($sName, $sPlace,
|
||||
'<!-- ko template: \''.$sLocalTemplateName.'\' --><!-- /ko -->', $bPrepend);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
73
rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Helper.php
Normal file
73
rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Helper.php
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Plugins;
|
||||
|
||||
class Helper
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sString
|
||||
* @param string $sWildcardValues
|
||||
* @param string $sFoundedValue = ''
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
static public function ValidateWildcardValues($sString, $sWildcardValues, &$sFoundedValue = '')
|
||||
{
|
||||
$sFoundedValue = '';
|
||||
|
||||
$sString = \trim($sString);
|
||||
if ('' === $sString)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$sWildcardValues = \trim($sWildcardValues);
|
||||
if ('' === $sWildcardValues)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ('*' === $sWildcardValues)
|
||||
{
|
||||
$sFoundedValue = '*';
|
||||
return true;
|
||||
}
|
||||
|
||||
$sWildcardValues = \preg_replace('/[*]+/', '*', \preg_replace('/[\s,;]+/', ' ', $sWildcardValues));
|
||||
$aWildcardValues = \explode(' ', $sWildcardValues);
|
||||
|
||||
foreach ($aWildcardValues as $sItem)
|
||||
{
|
||||
if (false === \strpos($sItem, '*'))
|
||||
{
|
||||
if ($sString === $sItem)
|
||||
{
|
||||
$sFoundedValue = $sItem;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aItem = \explode('*', $sItem);
|
||||
$aItem = \array_map(function ($sItem) {
|
||||
return \preg_quote($sItem, '/');
|
||||
}, $aItem);
|
||||
|
||||
if (\preg_match('/'.\implode('.*', $aItem).'/', $sString))
|
||||
{
|
||||
$sFoundedValue = $sItem;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
680
rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php
Normal file
680
rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Manager.php
Normal file
|
|
@ -0,0 +1,680 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Plugins;
|
||||
|
||||
class Manager
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Actions
|
||||
*/
|
||||
private $oActions;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aHooks;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aJs;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aAdminJs;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aTemplates;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aAdminTemplates;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aProcessTemplate;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aAdditionalParts;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aAdditionalAjax;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aPlugins;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bIsEnabled;
|
||||
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
private $oLogger;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Actions $oActions
|
||||
*/
|
||||
public function __construct(\RainLoop\Actions $oActions)
|
||||
{
|
||||
$this->oLogger = null;
|
||||
$this->oActions = $oActions;
|
||||
$this->aPlugins = array();
|
||||
|
||||
$this->aHooks = array();
|
||||
$this->aJs = array();
|
||||
$this->aAdminJs = array();
|
||||
$this->aTemplates = array();
|
||||
$this->aAdminTemplates = array();
|
||||
|
||||
$this->aAjaxFilters = array();
|
||||
$this->aAdditionalAjax = array();
|
||||
$this->aProcessTemplate = array();
|
||||
|
||||
$this->bIsEnabled = (bool) $this->oActions->Config()->Get('plugins', 'enable', false);
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
$sList = \strtolower($this->oActions->Config()->Get('plugins', 'enabled_list', ''));
|
||||
if (0 < \strlen($sList))
|
||||
{
|
||||
$aList = \explode(',', $sList);
|
||||
$aList = \array_map('trim', $aList);
|
||||
|
||||
foreach ($aList as $sName)
|
||||
{
|
||||
if (0 < \strlen($sName))
|
||||
{
|
||||
$oPlugin = $this->CreatePluginByName($sName);
|
||||
if ($oPlugin)
|
||||
{
|
||||
$oPlugin->PreInit();
|
||||
$oPlugin->Init();
|
||||
|
||||
$this->aPlugins[] = $oPlugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->RunHook('api.bootstrap.plugins');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return \RainLoop\Plugins\AbstractPlugin|null
|
||||
*/
|
||||
public function CreatePluginByName($sName)
|
||||
{
|
||||
$oPlugin = null;
|
||||
if (\preg_match('/^[a-z0-9\-]+$/', $sName) &&
|
||||
\file_exists(APP_PLUGINS_PATH.$sName.'/index.php'))
|
||||
{
|
||||
$sClassName = $this->convertPluginFolderNameToClassName($sName);
|
||||
|
||||
if (!\class_exists($sClassName))
|
||||
{
|
||||
include APP_PLUGINS_PATH.$sName.'/index.php';
|
||||
}
|
||||
|
||||
if (\class_exists($sClassName))
|
||||
{
|
||||
$oPlugin = new $sClassName();
|
||||
if ($oPlugin instanceof \RainLoop\Plugins\AbstractPlugin)
|
||||
{
|
||||
$oPlugin
|
||||
->SetName($sName)
|
||||
->SetPath(APP_PLUGINS_PATH.$sName)
|
||||
->SetVersion(\file_exists(APP_PLUGINS_PATH.$sName.'/VERSION') ?
|
||||
\file_get_contents(APP_PLUGINS_PATH.$sName.'/VERSION') : '')
|
||||
->SetPluginManager($this)
|
||||
->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap()))
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oPlugin = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $oPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function InstalledPlugins()
|
||||
{
|
||||
$aList = array();
|
||||
|
||||
$aGlob = @\glob(APP_PLUGINS_PATH.'*', GLOB_ONLYDIR|GLOB_NOSORT);
|
||||
if (\is_array($aGlob))
|
||||
{
|
||||
foreach ($aGlob as $sPathName)
|
||||
{
|
||||
$sName = \basename($sPathName);
|
||||
if (\preg_match('/^[a-z0-9\-]+$/', $sName) &&
|
||||
\file_exists($sPathName.'/index.php'))
|
||||
{
|
||||
$aList[] = array(
|
||||
$sName,
|
||||
\file_exists($sPathName.'/VERSION') ?
|
||||
\file_get_contents($sPathName.'/VERSION') : '0.0'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->Actions()->Logger()->Write('Cannot get installed plugins from '.APP_PLUGINS_PATH,
|
||||
\MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
|
||||
return $aList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFolderName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function convertPluginFolderNameToClassName($sFolderName)
|
||||
{
|
||||
$aParts = \array_map('ucfirst', \array_map('strtolower',
|
||||
\explode(' ', \preg_replace('/[^a-z0-9]+/', ' ', $sFolderName))));
|
||||
|
||||
return \implode($aParts).'Plugin';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Actions
|
||||
*/
|
||||
public function Actions()
|
||||
{
|
||||
return $this->oActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Hash()
|
||||
{
|
||||
$sResult = \md5(APP_VERSION);
|
||||
foreach ($this->aPlugins as $oPlugin)
|
||||
{
|
||||
$sResult = \md5($sResult.$oPlugin->Path().$oPlugin->Hash());
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAdminScope = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function CompileJs($bAdminScope = false)
|
||||
{
|
||||
$aResult = array();
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
$aJs = $bAdminScope ? $this->aAdminJs : $this->aJs;
|
||||
foreach ($aJs as $sFile)
|
||||
{
|
||||
if (\file_exists($sFile))
|
||||
{
|
||||
$aResult[] = \file_get_contents($sFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return \implode("\n", $aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo
|
||||
* @param bool $bAdminScope = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function CompileCss($bAdminScope = false)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAdminScope = false
|
||||
* @return string
|
||||
*/
|
||||
public function CompileTemplate($bAdminScope = false)
|
||||
{
|
||||
$sResult = '';
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
$aTemplates = $bAdminScope ? $this->aAdminTemplates : $this->aTemplates;
|
||||
foreach ($aTemplates as $sFile)
|
||||
{
|
||||
if (file_exists($sFile))
|
||||
{
|
||||
$sTemplateName = substr(basename($sFile), 0, -5);
|
||||
$sResult .= '<script id="'.preg_replace('/[^a-zA-Z0-9]/', '', $sTemplateName).'" type="text/html" data-cfasync="false">'.
|
||||
$this->Actions()->ProcessTemplate($sTemplateName, file_get_contents($sFile)).'</script>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAdmin
|
||||
* @param array $aAppData
|
||||
* @param \RainLoop\Model\Account|null $oAccount = null
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function InitAppData($bAdmin, &$aAppData, $oAccount = null)
|
||||
{
|
||||
if ($this->bIsEnabled && isset($aAppData['Plugins']) && \is_array($aAppData['Plugins']))
|
||||
{
|
||||
$bAuth = isset($aAppData['Auth']) && !!$aAppData['Auth'];
|
||||
foreach ($this->aPlugins as $oPlugin)
|
||||
{
|
||||
if ($oPlugin)
|
||||
{
|
||||
$aConfig = array();
|
||||
$aMap = $oPlugin->ConfigMap();
|
||||
if (\is_array($aMap))
|
||||
{
|
||||
foreach ($aMap as /* @var $oPluginProperty \RainLoop\Plugins\Property */ $oPluginProperty)
|
||||
{
|
||||
if ($oPluginProperty && $oPluginProperty->AllowedInJs())
|
||||
{
|
||||
$aConfig[$oPluginProperty->Name()] =
|
||||
$oPlugin->Config()->Get('plugin',
|
||||
$oPluginProperty->Name(),
|
||||
$oPluginProperty->DefaultValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oPlugin->FilterAppDataPluginSection($bAdmin, $bAuth, $aConfig);
|
||||
|
||||
if (0 < \count($aConfig))
|
||||
{
|
||||
$aAppData['Plugins'][$oPlugin->Name()] = $aConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->RunHook('filter.app-data', array($bAdmin, &$aAppData));
|
||||
|
||||
$this->RunHook('filter.app-data[2]', array(
|
||||
'IsAdmin' => $bAdmin,
|
||||
'AppData' => &$aAppData,
|
||||
'Account' => $oAccount
|
||||
));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHookName
|
||||
* @param mixed $mCallbak
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function AddHook($sHookName, $mCallbak)
|
||||
{
|
||||
if ($this->bIsEnabled && \is_callable($mCallbak))
|
||||
{
|
||||
if (!isset($this->aHooks[$sHookName]))
|
||||
{
|
||||
$this->aHooks[$sHookName] = array();
|
||||
}
|
||||
|
||||
$this->aHooks[$sHookName][] = $mCallbak;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFile
|
||||
* @param bool $bAdminScope = false
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function AddJs($sFile, $bAdminScope = false)
|
||||
{
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
if ($bAdminScope)
|
||||
{
|
||||
$this->aAdminJs[$sFile] = $sFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aJs[$sFile] = $sFile;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFile
|
||||
* @param bool $bAdminScope = false
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function AddTemplate($sFile, $bAdminScope = false)
|
||||
{
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
if ($bAdminScope)
|
||||
{
|
||||
$this->aAdminTemplates[$sFile] = $sFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->aTemplates[$sFile] = $sFile;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sHookName
|
||||
* @param array $aArg = array()
|
||||
* @param bool $bLogHook = true
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function RunHook($sHookName, $aArg = array(), $bLogHook = true)
|
||||
{
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
if (isset($this->aHooks[$sHookName]))
|
||||
{
|
||||
if ($bLogHook)
|
||||
{
|
||||
$this->WriteLog('Hook: '.$sHookName, \MailSo\Log\Enumerations\Type::NOTE);
|
||||
}
|
||||
|
||||
foreach ($this->aHooks[$sHookName] as $mCallback)
|
||||
{
|
||||
\call_user_func_array($mCallback, $aArg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sActionName
|
||||
* @param mixed $mCallbak
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function AddAdditionalPartAction($sActionName, $mCallbak)
|
||||
{
|
||||
if ($this->bIsEnabled && \is_callable($mCallbak))
|
||||
{
|
||||
$sActionName = \strtolower($sActionName);
|
||||
if (!isset($this->aAdditionalParts[$sActionName]))
|
||||
{
|
||||
$this->aAdditionalParts[$sActionName] = array();
|
||||
}
|
||||
|
||||
$this->aAdditionalParts[$sActionName][] = $mCallbak;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sActionName
|
||||
* @param array $aParts = array()
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function RunAdditionalPart($sActionName, $aParts = array())
|
||||
{
|
||||
$bResult = false;
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
$sActionName = \strtolower($sActionName);
|
||||
if (isset($this->aAdditionalParts[$sActionName]))
|
||||
{
|
||||
foreach ($this->aAdditionalParts[$sActionName] as $mCallbak)
|
||||
{
|
||||
$bCallResult = \call_user_func_array($mCallbak, $aParts);
|
||||
if ($bCallResult && !$bResult)
|
||||
{
|
||||
$bResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sPlace
|
||||
* @param string $sHtml
|
||||
* @param bool $bPrepend = false
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function AddProcessTemplateAction($sName, $sPlace, $sHtml, $bPrepend = false)
|
||||
{
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
if (!isset($this->aProcessTemplate[$sName]))
|
||||
{
|
||||
$this->aProcessTemplate[$sName] = array();
|
||||
}
|
||||
|
||||
if (!isset($this->aProcessTemplate[$sName][$sPlace]))
|
||||
{
|
||||
$this->aProcessTemplate[$sName][$sPlace] = array();
|
||||
}
|
||||
|
||||
if ($bPrepend)
|
||||
{
|
||||
\array_unshift($this->aProcessTemplate[$sName][$sPlace], $sHtml);
|
||||
}
|
||||
else
|
||||
{
|
||||
\array_push($this->aProcessTemplate[$sName][$sPlace], $sHtml);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sActionName
|
||||
* @param mixed $mCallbak
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function AddAdditionalAjaxAction($sActionName, $mCallbak)
|
||||
{
|
||||
if ($this->bIsEnabled && \is_callable($mCallbak) && 0 < \strlen($sActionName))
|
||||
{
|
||||
$sActionName = 'Do'.$sActionName;
|
||||
|
||||
if (!isset($this->aAdditionalAjax[$sActionName]))
|
||||
{
|
||||
$this->aAdditionalAjax[$sActionName] = $mCallbak;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sActionName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function HasAdditionalAjax($sActionName)
|
||||
{
|
||||
return $this->bIsEnabled && isset($this->aAdditionalAjax[$sActionName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sActionName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function RunAdditionalAjax($sActionName)
|
||||
{
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
if (isset($this->aAdditionalAjax[$sActionName]))
|
||||
{
|
||||
return \call_user_func($this->aAdditionalAjax[$sActionName]);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sLang
|
||||
* @param array $sActionName
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*/
|
||||
public function ReadLang($sLang, &$aLang)
|
||||
{
|
||||
if ($this->bIsEnabled)
|
||||
{
|
||||
foreach ($this->aPlugins as $oPlugin)
|
||||
{
|
||||
if ($oPlugin->UseLangs())
|
||||
{
|
||||
$sPath = $oPlugin->Path();
|
||||
|
||||
\RainLoop\Utils::ReadAndAddLang($sPath.'/langs/en.ini', $aLang);
|
||||
if ('en' !== $sLang)
|
||||
{
|
||||
\RainLoop\Utils::ReadAndAddLang($sPath.'/langs/'.$sLang.'.ini', $aLang);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sHtml
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ProcessTemplate($sName, $sHtml)
|
||||
{
|
||||
if (isset($this->aProcessTemplate[$sName]))
|
||||
{
|
||||
foreach ($this->aProcessTemplate[$sName] as $sPlace => $aAddHtml)
|
||||
{
|
||||
if (\is_array($aAddHtml) && 0 < \count($aAddHtml))
|
||||
{
|
||||
foreach ($aAddHtml as $sAddHtml)
|
||||
{
|
||||
$sHtml = \str_replace('{{INCLUDE/'.$sPlace.'/PLACE}}', $sAddHtml.'{{INCLUDE/'.$sPlace.'/PLACE}}', $sHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function bIsEnabled()
|
||||
{
|
||||
return $this->bIsEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function Count()
|
||||
{
|
||||
return $this->bIsEnabled ? \count($this->aPlugins) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Log\Logger $oLogger
|
||||
*
|
||||
* @return \RainLoop\Plugins\Manager
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public function SetLogger($oLogger)
|
||||
{
|
||||
if (!($oLogger instanceof \MailSo\Log\Logger))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||
}
|
||||
|
||||
$this->oLogger = $oLogger;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDesc
|
||||
* @param int $iType = \MailSo\Log\Enumerations\Type::INFO
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function WriteLog($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write($sDesc, $iType, 'PLUGIN');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDesc
|
||||
* @param int $iType = \MailSo\Log\Enumerations\Type::INFO
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function WriteException($sDesc, $iType = \MailSo\Log\Enumerations\Type::INFO)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->WriteException($sDesc, $iType, 'PLUGIN');
|
||||
}
|
||||
}
|
||||
}
|
||||
205
rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Property.php
Normal file
205
rainloop/v/0.0.0/app/libraries/RainLoop/Plugins/Property.php
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Plugins;
|
||||
|
||||
class Property
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sLabel;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDesc;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $iType;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bAllowedInJs;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $mDefaultValue;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sPlaceholder;
|
||||
|
||||
private function __construct($sName)
|
||||
{
|
||||
$this->sName = $sName;
|
||||
$this->iType = \RainLoop\Enumerations\PluginPropertyType::STRING;
|
||||
$this->mDefaultValue = '';
|
||||
$this->sLabel = '';
|
||||
$this->sDesc = '';
|
||||
$this->bAllowedInJs = false;
|
||||
$this->sPlaceholder = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return \RainLoop\Plugins\Property
|
||||
*/
|
||||
public static function NewInstance($sName)
|
||||
{
|
||||
return new self($sName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iType
|
||||
*
|
||||
* @return \RainLoop\Plugins\Property
|
||||
*/
|
||||
public function SetType($iType)
|
||||
{
|
||||
$this->iType = (int) $iType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $mDefaultValue
|
||||
*
|
||||
* @return \RainLoop\Plugins\Property
|
||||
*/
|
||||
public function SetDefaultValue($mDefaultValue)
|
||||
{
|
||||
$this->mDefaultValue = $mDefaultValue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPlaceholder
|
||||
*
|
||||
* @return \RainLoop\Plugins\Property
|
||||
*/
|
||||
public function SetPlaceholder($sPlaceholder)
|
||||
{
|
||||
$this->sPlaceholder = $sPlaceholder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sLabel
|
||||
*
|
||||
* @return \RainLoop\Plugins\Property
|
||||
*/
|
||||
public function SetLabel($sLabel)
|
||||
{
|
||||
$this->sLabel = $sLabel;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDesc
|
||||
*
|
||||
* @return \RainLoop\Plugins\Property
|
||||
*/
|
||||
public function SetDescription($sDesc)
|
||||
{
|
||||
$this->sDesc = $sDesc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bValue = true
|
||||
* @return \RainLoop\Plugins\Property
|
||||
*/
|
||||
public function SetAllowedInJs($bValue = true)
|
||||
{
|
||||
$this->bAllowedInJs = !!$bValue;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Name()
|
||||
{
|
||||
return $this->sName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function AllowedInJs()
|
||||
{
|
||||
return $this->bAllowedInJs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Description()
|
||||
{
|
||||
return $this->sDesc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Label()
|
||||
{
|
||||
return $this->sLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function Type()
|
||||
{
|
||||
return $this->iType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function DefaultValue()
|
||||
{
|
||||
return $this->mDefaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Placeholder()
|
||||
{
|
||||
return $this->sPlaceholder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function ToArray()
|
||||
{
|
||||
return array(
|
||||
'',
|
||||
$this->sName,
|
||||
$this->iType,
|
||||
$this->sLabel,
|
||||
$this->mDefaultValue,
|
||||
$this->sDesc,
|
||||
$this->sPlaceholder
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
abstract class AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Model\Account
|
||||
*/
|
||||
protected $oAccount;
|
||||
|
||||
/**
|
||||
* @var \MailSo\Log\Logger
|
||||
*/
|
||||
protected $oLogger = null;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
*/
|
||||
public function SetAccount($oAccount)
|
||||
{
|
||||
$this->oAccount = $oAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Log\Logger $oLogger
|
||||
*/
|
||||
public function SetLogger($oLogger)
|
||||
{
|
||||
if ($oLogger instanceof \MailSo\Log\Logger)
|
||||
{
|
||||
$this->oLogger = $oLogger;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \MailSo\Log\Logger|null
|
||||
*/
|
||||
public function Logger()
|
||||
{
|
||||
return $this->oLogger;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,374 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
use \RainLoop\Providers\AddressBook\Enumerations\PropertyType as PropertyType;
|
||||
|
||||
class AddressBook extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\AddressBook\AddressBookInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\AddressBook\Interface $oDriver
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($oDriver)
|
||||
{
|
||||
$this->oDriver = null;
|
||||
if ($oDriver instanceof \RainLoop\Providers\AddressBook\AddressBookInterface)
|
||||
{
|
||||
$this->oDriver = $oDriver;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Test()
|
||||
{
|
||||
\sleep(1);
|
||||
return $this->oDriver instanceof \RainLoop\Providers\AddressBook\AddressBookInterface ?
|
||||
$this->oDriver->Test() : 'Personal address book driver is not allowed';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\AddressBook\AddressBookInterface &&
|
||||
$this->oDriver->IsSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsSupported()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\AddressBook\AddressBookInterface &&
|
||||
$this->oDriver->IsSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsSharingAllowed()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\AddressBook\AddressBookInterface &&
|
||||
$this->oDriver->IsSharingAllowed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sUrl
|
||||
* @param string $sUser
|
||||
* @param string $sPassword
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Sync($sEmail, $sUrl, $sUser, $sPassword)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->Sync($sEmail, $sUrl, $sUser, $sPassword) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sType = 'vcf'
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Export($sEmail, $sType = 'vcf')
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->Export($sEmail, $sType) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param \RainLoop\Providers\AddressBook\Classes\Contact $oContact
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ContactSave($sEmail, &$oContact)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->ContactSave($sEmail, $oContact) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param array $aContactIds
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteContacts($sEmail, $aContactIds)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->DeleteContacts($sEmail, $aContactIds) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteAllContacts($sEmail)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->DeleteAllContacts($sEmail) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param int $iOffset = 0
|
||||
* @param type $iLimit = 20
|
||||
* @param string $sSearch = ''
|
||||
* @param int $iResultCount = 0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetContacts($sEmail, $iOffset = 0, $iLimit = 20, $sSearch = '', &$iResultCount = 0)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->GetContacts($sEmail,
|
||||
$iOffset, $iLimit, $sSearch, $iResultCount) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $mID
|
||||
* @param bool $bIsStrID = false
|
||||
*
|
||||
* @return \RainLoop\Providers\AddressBook\Classes\Contact|null
|
||||
*/
|
||||
public function GetContactByID($sEmail, $mID, $bIsStrID = false)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->GetContactByID($sEmail, $mID, $bIsStrID) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sSearch
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function GetSuggestions($sEmail, $sSearch, $iLimit = 20)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->GetSuggestions($sEmail, $sSearch, $iLimit) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param array $aEmails
|
||||
* @param bool $bCreateAuto = true
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IncFrec($sEmail, $aEmails, $bCreateAuto = true)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->IncFrec($sEmail, $aEmails, $bCreateAuto) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sCsvName
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function csvNameToTypeConvertor($sCsvName)
|
||||
{
|
||||
static $aMap = null;
|
||||
if (null === $aMap)
|
||||
{
|
||||
$aMap = array(
|
||||
'Title' => PropertyType::FULLNAME,
|
||||
'Name' => PropertyType::FULLNAME,
|
||||
'FullName' => PropertyType::FULLNAME,
|
||||
'DisplayName' => PropertyType::FULLNAME,
|
||||
'GivenName' => PropertyType::FULLNAME,
|
||||
'First' => PropertyType::FIRST_NAME,
|
||||
'FirstName' => PropertyType::FIRST_NAME,
|
||||
'Middle' => PropertyType::MIDDLE_NAME,
|
||||
'MiddleName' => PropertyType::MIDDLE_NAME,
|
||||
'Last' => PropertyType::LAST_NAME,
|
||||
'LastName' => PropertyType::LAST_NAME,
|
||||
'Suffix' => PropertyType::NAME_SUFFIX,
|
||||
'NameSuffix' => PropertyType::NAME_SUFFIX,
|
||||
'Prefix' => PropertyType::NAME_PREFIX,
|
||||
'NamePrefix' => PropertyType::NAME_PREFIX,
|
||||
'ShortName' => PropertyType::NICK_NAME,
|
||||
'NickName' => PropertyType::NICK_NAME,
|
||||
'BusinessFax' => array(PropertyType::PHONE, 'Work,Fax'),
|
||||
'BusinessFax2' => array(PropertyType::PHONE, 'Work,Fax'),
|
||||
'BusinessFax3' => array(PropertyType::PHONE, 'Work,Fax'),
|
||||
'BusinessPhone' => array(PropertyType::PHONE, 'Work'),
|
||||
'BusinessPhone2' => array(PropertyType::PHONE, 'Work'),
|
||||
'BusinessPhone3' => array(PropertyType::PHONE, 'Work'),
|
||||
'CompanyPhone' => array(PropertyType::PHONE, 'Work'),
|
||||
'CompanyMainPhone' => array(PropertyType::PHONE, 'Work'),
|
||||
'HomeFax' => array(PropertyType::PHONE, 'Home,Fax'),
|
||||
'HomeFax2' => array(PropertyType::PHONE, 'Home,Fax'),
|
||||
'HomeFax3' => array(PropertyType::PHONE, 'Home,Fax'),
|
||||
'HomePhone' => array(PropertyType::PHONE, 'Home'),
|
||||
'HomePhone2' => array(PropertyType::PHONE, 'Home'),
|
||||
'HomePhone3' => array(PropertyType::PHONE, 'Home'),
|
||||
'Mobile' => array(PropertyType::PHONE, 'Mobile'),
|
||||
'MobilePhone' => array(PropertyType::PHONE, 'Mobile'),
|
||||
'BusinessMobile' => array(PropertyType::PHONE, 'Work,Mobile'),
|
||||
'BusinessMobilePhone' => array(PropertyType::PHONE, 'Work,Mobile'),
|
||||
'OtherFax' => array(PropertyType::PHONE, 'Other,Fax'),
|
||||
'OtherPhone' => array(PropertyType::PHONE, 'Other'),
|
||||
'PrimaryPhone' => array(PropertyType::PHONE, 'Pref,Home'),
|
||||
'Email' => array(PropertyType::EMAIl, 'Home'),
|
||||
'Email2' => array(PropertyType::EMAIl, 'Home'),
|
||||
'Email3' => array(PropertyType::EMAIl, 'Home'),
|
||||
'HomeEmail' => array(PropertyType::EMAIl, 'Home'),
|
||||
'HomeEmail2' => array(PropertyType::EMAIl, 'Home'),
|
||||
'HomeEmail3' => array(PropertyType::EMAIl, 'Home'),
|
||||
'EmailAddress' => array(PropertyType::EMAIl, 'Home'),
|
||||
'Email2Address' => array(PropertyType::EMAIl, 'Home'),
|
||||
'Email3Address' => array(PropertyType::EMAIl, 'Home'),
|
||||
'OtherEmail' => array(PropertyType::EMAIl, 'Other'),
|
||||
'BusinessEmail' => array(PropertyType::EMAIl, 'Work'),
|
||||
'BusinessEmail2' => array(PropertyType::EMAIl, 'Work'),
|
||||
'BusinessEmail3' => array(PropertyType::EMAIl, 'Work'),
|
||||
'PersonalEmail' => array(PropertyType::EMAIl, 'Home'),
|
||||
'PersonalEmail2' => array(PropertyType::EMAIl, 'Home'),
|
||||
'PersonalEmail3' => array(PropertyType::EMAIl, 'Home'),
|
||||
'Notes' => PropertyType::NOTE,
|
||||
'Web' => PropertyType::WEB_PAGE,
|
||||
'BusinessWeb' => array(PropertyType::WEB_PAGE, 'Work'),
|
||||
'WebPage' => PropertyType::WEB_PAGE,
|
||||
'BusinessWebPage' => array(PropertyType::WEB_PAGE, 'Work'),
|
||||
'WebSite' => PropertyType::WEB_PAGE,
|
||||
'BusinessWebSite' => array(PropertyType::WEB_PAGE, 'Work'),
|
||||
'PersonalWebSite' => PropertyType::WEB_PAGE
|
||||
);
|
||||
|
||||
$aMap = \array_change_key_case($aMap, CASE_LOWER);
|
||||
}
|
||||
|
||||
$sCsvNameLower = \MailSo\Base\Utils::IsAscii($sCsvName) ? \preg_replace('/[\s\-]+/', '', \strtolower($sCsvName)) : '';
|
||||
return !empty($sCsvNameLower) && isset($aMap[$sCsvNameLower]) ? $aMap[$sCsvNameLower] : PropertyType::UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param array $aCsvData
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function ImportCsvArray($sEmail, $aCsvData)
|
||||
{
|
||||
$iCount = 0;
|
||||
if ($this->IsActive() && \is_array($aCsvData) && 0 < \count($aCsvData))
|
||||
{
|
||||
$oContact = new \RainLoop\Providers\AddressBook\Classes\Contact();
|
||||
foreach ($aCsvData as $aItem)
|
||||
{
|
||||
\MailSo\Base\Utils::ResetTimeLimit();
|
||||
|
||||
foreach ($aItem as $sItemName => $sItemValue)
|
||||
{
|
||||
$sItemName = \trim($sItemName);
|
||||
$sItemValue = \trim($sItemValue);
|
||||
|
||||
if (!empty($sItemName) && !empty($sItemValue))
|
||||
{
|
||||
$mData = $this->csvNameToTypeConvertor($sItemName);
|
||||
$iType = \is_array($mData) ? $mData[0] : $mData;
|
||||
|
||||
if (PropertyType::UNKNOWN !== $iType)
|
||||
{
|
||||
$oProp = new \RainLoop\Providers\AddressBook\Classes\Property();
|
||||
$oProp->Type = $iType;
|
||||
$oProp->Value = $sItemValue;
|
||||
$oProp->TypeStr = \is_array($mData) && !empty($mData[1]) ? $mData[1] : '';
|
||||
|
||||
$oContact->Properties[] = $oProp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($oContact && 0 < \count($oContact->Properties))
|
||||
{
|
||||
if ($this->ContactSave($sEmail, $oContact))
|
||||
{
|
||||
$iCount++;
|
||||
}
|
||||
}
|
||||
|
||||
$oContact->Clear();
|
||||
}
|
||||
|
||||
unset($oContact);
|
||||
}
|
||||
|
||||
return $iCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sVcfData
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function ImportVcfFile($sEmail, $sVcfData)
|
||||
{
|
||||
$iCount = 0;
|
||||
|
||||
if (\class_exists('Sabre\DAV\Client') && $this->IsActive() && \is_string($sVcfData))
|
||||
{
|
||||
$sVcfData = \trim($sVcfData);
|
||||
if ("\xef\xbb\xbf" === \substr($sVcfData, 0, 3))
|
||||
{
|
||||
$sVcfData = \substr($sVcfData, 3);
|
||||
}
|
||||
|
||||
$oVCardSplitter = null;
|
||||
try
|
||||
{
|
||||
$oVCardSplitter = new \Sabre\VObject\Splitter\VCard($sVcfData);
|
||||
}
|
||||
catch (\Exception $oExc)
|
||||
{
|
||||
$this->Logger()->WriteException($oExc);
|
||||
}
|
||||
|
||||
if ($oVCardSplitter)
|
||||
{
|
||||
$oContact = new \RainLoop\Providers\AddressBook\Classes\Contact();
|
||||
|
||||
$oVCard = null;
|
||||
|
||||
while ($oVCard = $oVCardSplitter->getNext())
|
||||
{
|
||||
if ($oVCard instanceof \Sabre\VObject\Component\VCard)
|
||||
{
|
||||
\MailSo\Base\Utils::ResetTimeLimit();
|
||||
|
||||
if (empty($oVCard->UID))
|
||||
{
|
||||
$oVCard->UID = \Sabre\DAV\UUIDUtil::getUUID();
|
||||
}
|
||||
|
||||
$oContact->PopulateByVCard($oVCard->serialize());
|
||||
|
||||
if (0 < \count($oContact->Properties))
|
||||
{
|
||||
if ($this->ContactSave($sEmail, $oContact))
|
||||
{
|
||||
$iCount++;
|
||||
}
|
||||
}
|
||||
|
||||
$oContact->Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $iCount;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\AddressBook;
|
||||
|
||||
interface AddressBookInterface
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsSupported();
|
||||
}
|
||||
|
|
@ -0,0 +1,596 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\AddressBook\Classes;
|
||||
|
||||
use
|
||||
RainLoop\Providers\AddressBook\Enumerations\PropertyType,
|
||||
RainLoop\Providers\AddressBook\Classes\Property
|
||||
;
|
||||
|
||||
class Contact
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $IdContact;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $IdContactStr;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $Display;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $Changed;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $Properties;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $ReadOnly;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $IdPropertyFromSearch;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $Etag;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->Clear();
|
||||
}
|
||||
|
||||
public function Clear()
|
||||
{
|
||||
$this->IdContact = '';
|
||||
$this->IdContactStr = '';
|
||||
$this->Display = '';
|
||||
$this->Changed = \time();
|
||||
$this->Properties = array();
|
||||
$this->ReadOnly = false;
|
||||
$this->IdPropertyFromSearch = 0;
|
||||
$this->Etag = '';
|
||||
}
|
||||
|
||||
public function UpdateDependentValues()
|
||||
{
|
||||
$sLastName = '';
|
||||
$sFirstName = '';
|
||||
$sEmail = '';
|
||||
$sOther = '';
|
||||
|
||||
$oFullNameProperty = null;
|
||||
|
||||
foreach ($this->Properties as /* @var $oProperty \RainLoop\Providers\AddressBook\Classes\Property */ &$oProperty)
|
||||
{
|
||||
if ($oProperty)
|
||||
{
|
||||
$oProperty->UpdateDependentValues();
|
||||
|
||||
if (!$oFullNameProperty && PropertyType::FULLNAME === $oProperty->Type)
|
||||
{
|
||||
$oFullNameProperty =& $oProperty;
|
||||
}
|
||||
|
||||
if (0 < \strlen($oProperty->Value))
|
||||
{
|
||||
if ('' === $sEmail && $oProperty->IsEmail())
|
||||
{
|
||||
$sEmail = $oProperty->Value;
|
||||
}
|
||||
else if ('' === $sLastName && PropertyType::LAST_NAME === $oProperty->Type)
|
||||
{
|
||||
$sLastName = $oProperty->Value;
|
||||
}
|
||||
else if ('' === $sFirstName && PropertyType::FIRST_NAME === $oProperty->Type)
|
||||
{
|
||||
$sFirstName = $oProperty->Value;
|
||||
}
|
||||
else if (\in_array($oProperty->Type, array(
|
||||
PropertyType::FULLNAME, PropertyType::PHONE
|
||||
)))
|
||||
{
|
||||
$sOther = $oProperty->Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->IdContactStr))
|
||||
{
|
||||
$this->RegenerateContactStr();
|
||||
}
|
||||
|
||||
$sDisplay = '';
|
||||
if (0 < \strlen($sLastName) || 0 < \strlen($sFirstName))
|
||||
{
|
||||
$sDisplay = \trim($sFirstName.' '.$sLastName);
|
||||
}
|
||||
|
||||
if ('' === $sDisplay && 0 < \strlen($sEmail))
|
||||
{
|
||||
$sDisplay = \trim($sEmail);
|
||||
}
|
||||
|
||||
if ('' === $sDisplay)
|
||||
{
|
||||
$sDisplay = $sOther;
|
||||
}
|
||||
|
||||
$this->Display = \trim($sDisplay);
|
||||
|
||||
if ($oFullNameProperty)
|
||||
{
|
||||
$oFullNameProperty->Value = $this->Display;
|
||||
$oFullNameProperty->UpdateDependentValues();
|
||||
}
|
||||
|
||||
if (!$oFullNameProperty)
|
||||
{
|
||||
$this->Properties[] = new \RainLoop\Providers\AddressBook\Classes\Property(PropertyType::FULLNAME, $this->Display);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function RegenerateContactStr()
|
||||
{
|
||||
$this->IdContactStr = \class_exists('Sabre\DAV\Client') ?
|
||||
\Sabre\DAV\UUIDUtil::getUUID() : \md5(\microtime(true).'-'.\rand(10000, 99999));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GetEmails()
|
||||
{
|
||||
$aResult = array();
|
||||
foreach ($this->Properties as /* @var $oProperty \RainLoop\Providers\AddressBook\Classes\Property */ &$oProperty)
|
||||
{
|
||||
if ($oProperty && $oProperty->IsEmail())
|
||||
{
|
||||
$aResult[] = $oProperty->Value;
|
||||
}
|
||||
}
|
||||
|
||||
return \array_unique($aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function CardDavNameUri()
|
||||
{
|
||||
return $this->IdContactStr.'.vcf';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ToVCard($sPreVCard = '')
|
||||
{
|
||||
$this->UpdateDependentValues();
|
||||
|
||||
if (!\class_exists('Sabre\DAV\Client'))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
$oVCard = null;
|
||||
if (0 < \strlen($sPreVCard))
|
||||
{
|
||||
try
|
||||
{
|
||||
$oVCard = \Sabre\VObject\Reader::read($sPreVCard);
|
||||
}
|
||||
catch (\Exception $oExc) {};
|
||||
}
|
||||
|
||||
if (!$oVCard)
|
||||
{
|
||||
$oVCard = new \Sabre\VObject\Component\VCard();
|
||||
}
|
||||
|
||||
$oVCard->VERSION = '3.0';
|
||||
$oVCard->PRODID = '-//RainLoop//'.APP_VERSION.'//EN';
|
||||
|
||||
unset($oVCard->FN, $oVCard->EMAIL, $oVCard->TEL, $oVCard->URL, $oVCard->NICKNAME);
|
||||
|
||||
$sFirstName = $sLastName = $sMiddleName = $sSuffix = $sPrefix = '';
|
||||
foreach ($this->Properties as /* @var $oProperty \RainLoop\Providers\AddressBook\Classes\Property */ &$oProperty)
|
||||
{
|
||||
if ($oProperty)
|
||||
{
|
||||
$sAddKey = '';
|
||||
switch ($oProperty->Type)
|
||||
{
|
||||
case PropertyType::FULLNAME:
|
||||
$oVCard->FN = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::NICK_NAME:
|
||||
$oVCard->NICKNAME = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::NOTE:
|
||||
$oVCard->NOTE = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::FIRST_NAME:
|
||||
$sFirstName = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::LAST_NAME:
|
||||
$sLastName = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::MIDDLE_NAME:
|
||||
$sMiddleName = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::NAME_SUFFIX:
|
||||
$sSuffix = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::NAME_PREFIX:
|
||||
$sPrefix = $oProperty->Value;
|
||||
break;
|
||||
case PropertyType::EMAIl:
|
||||
if (empty($sAddKey))
|
||||
{
|
||||
$sAddKey = 'EMAIL';
|
||||
}
|
||||
case PropertyType::WEB_PAGE:
|
||||
if (empty($sAddKey))
|
||||
{
|
||||
$sAddKey = 'URL';
|
||||
}
|
||||
case PropertyType::PHONE:
|
||||
if (empty($sAddKey))
|
||||
{
|
||||
$sAddKey = 'TEL';
|
||||
}
|
||||
|
||||
$aTypes = $oProperty->TypesAsArray();
|
||||
$oVCard->add($sAddKey, $oProperty->Value, \is_array($aTypes) && 0 < \count($aTypes) ? array('TYPE' => $aTypes) : null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oVCard->UID = $this->IdContactStr;
|
||||
$oVCard->N = array($sLastName, $sFirstName, $sMiddleName, $sPrefix, $sSuffix);
|
||||
$oVCard->REV = \gmdate('Ymd', $this->Changed).'T'.\gmdate('His', $this->Changed).'Z';
|
||||
|
||||
return (string) $oVCard->serialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ToCsv($bWithHeader = false)
|
||||
{
|
||||
$aData = array();
|
||||
if ($bWithHeader)
|
||||
{
|
||||
$aData[] = array(
|
||||
'Title', 'First Name', 'Middle Name', 'Last Name', 'Nick Name', 'Display Name',
|
||||
'Company', 'Department', 'Job Title', 'Office Location',
|
||||
'E-mail Address', 'Notes', 'Web Page', 'Birthday',
|
||||
'Other Email', 'Other Phone', 'Other Mobile', 'Mobile Phone',
|
||||
'Home Email', 'Home Phone', 'Home Fax',
|
||||
'Home Street', 'Home City', 'Home State', 'Home Postal Code', 'Home Country',
|
||||
'Business Email', 'Business Phone', 'Business Fax',
|
||||
'Business Street', 'Business City', 'Business State', 'Business Postal Code', 'Business Country'
|
||||
);
|
||||
}
|
||||
|
||||
$aValues = array(
|
||||
'', // 0 'Title',
|
||||
'', // 1 'First Name',
|
||||
'', // 2 'Middle Name',
|
||||
'', // 3 'Last Name',
|
||||
'', // 4 'Nick Name',
|
||||
'', // 5 'Display Name',
|
||||
'', // 6 'Company',
|
||||
'', // 7 'Department',
|
||||
'', // 8 'Job Title',
|
||||
'', // 9 'Office Location',
|
||||
'', // 10 'E-mail Address',
|
||||
'', // 11 'Notes',
|
||||
'', // 12 'Web Page',
|
||||
'', // 13 'Birthday',
|
||||
'', // 14 'Other Email',
|
||||
'', // 15 'Other Phone',
|
||||
'', // 16 'Other Mobile',
|
||||
'', // 17 'Mobile Phone',
|
||||
'', // 18 'Home Email',
|
||||
'', // 19 'Home Phone',
|
||||
'', // 20 'Home Fax',
|
||||
'', // 21 'Home Street',
|
||||
'', // 22 'Home City',
|
||||
'', // 23 'Home State',
|
||||
'', // 24 'Home Postal Code',
|
||||
'', // 25 'Home Country',
|
||||
'', // 26 'Business Email',
|
||||
'', // 27 'Business Phone',
|
||||
'', // 28 'Business Fax',
|
||||
'', // 29 'Business Street',
|
||||
'', // 30 'Business City',
|
||||
'', // 31 'Business State',
|
||||
'', // 32 'Business Postal Code',
|
||||
'' // 33 'Business Country'
|
||||
);
|
||||
|
||||
$this->UpdateDependentValues();
|
||||
|
||||
foreach ($this->Properties as /* @var $oProperty \RainLoop\Providers\AddressBook\Classes\Property */ &$oProperty)
|
||||
{
|
||||
$iIndex = -1;
|
||||
if ($oProperty)
|
||||
{
|
||||
$aUpperTypes = $oProperty->TypesUpperAsArray();
|
||||
switch ($oProperty->Type)
|
||||
{
|
||||
case PropertyType::FULLNAME:
|
||||
$iIndex = 5;
|
||||
break;
|
||||
case PropertyType::NICK_NAME:
|
||||
$iIndex = 4;
|
||||
break;
|
||||
case PropertyType::FIRST_NAME:
|
||||
$iIndex = 1;
|
||||
break;
|
||||
case PropertyType::LAST_NAME:
|
||||
$iIndex = 3;
|
||||
break;
|
||||
case PropertyType::MIDDLE_NAME:
|
||||
$iIndex = 2;
|
||||
break;
|
||||
case PropertyType::EMAIl:
|
||||
switch (true)
|
||||
{
|
||||
case \in_array('OTHER', $aUpperTypes):
|
||||
$iIndex = 14;
|
||||
break;
|
||||
case \in_array('WORK', $aUpperTypes):
|
||||
$iIndex = 26;
|
||||
break;
|
||||
default:
|
||||
$iIndex = 18;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PropertyType::PHONE:
|
||||
switch (true)
|
||||
{
|
||||
case \in_array('OTHER', $aUpperTypes):
|
||||
$iIndex = 15;
|
||||
break;
|
||||
case \in_array('WORK', $aUpperTypes):
|
||||
$iIndex = 27;
|
||||
break;
|
||||
case \in_array('MOBILE', $aUpperTypes):
|
||||
$iIndex = 17;
|
||||
break;
|
||||
default:
|
||||
$iIndex = 19;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PropertyType::WEB_PAGE:
|
||||
$iIndex = 12;
|
||||
break;
|
||||
case PropertyType::NOTE:
|
||||
$iIndex = 11;
|
||||
break;
|
||||
}
|
||||
|
||||
if (-1 < $iIndex)
|
||||
{
|
||||
$aValues[$iIndex] = $oProperty->Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// subfix
|
||||
if (empty($aValues[10])) // 'E-mail Address'
|
||||
{
|
||||
if (!empty($aValues[18]))
|
||||
{
|
||||
$aValues[10] = $aValues[18];
|
||||
}
|
||||
else if (!empty($aValues[26]))
|
||||
{
|
||||
$aValues[10] = $aValues[26];
|
||||
}
|
||||
else if (!empty($aValues[14]))
|
||||
{
|
||||
$aValues[10] = $aValues[14];
|
||||
}
|
||||
}
|
||||
|
||||
$aData[] = \array_map(function ($sValue) {
|
||||
$sValue = \trim($sValue);
|
||||
return \preg_match('/[\r\n,"]/', $sValue) ? '"'.\str_replace('"', '""', $sValue).'"' : $sValue;
|
||||
}, $aValues);
|
||||
|
||||
$sResult = '';
|
||||
foreach ($aData as $aSubData)
|
||||
{
|
||||
$sResult .= \implode(',', $aSubData)."\r\n";
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $oProp
|
||||
* @param bool $bOldVersion
|
||||
* @return string
|
||||
*/
|
||||
private function getPropertyValueHelper($oProp, $bOldVersion)
|
||||
{
|
||||
$sValue = \trim($oProp);
|
||||
if ($bOldVersion && !isset($oProp->parameters['CHARSET']))
|
||||
{
|
||||
if (0 < \strlen($sValue))
|
||||
{
|
||||
$sEncValue = @\utf8_encode($sValue);
|
||||
if (0 === \strlen($sEncValue))
|
||||
{
|
||||
$sEncValue = $sValue;
|
||||
}
|
||||
|
||||
$sValue = $sEncValue;
|
||||
}
|
||||
}
|
||||
|
||||
return \MailSo\Base\Utils::Utf8Clear($sValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $oProp
|
||||
* @param bool $bOldVersion
|
||||
* @return string
|
||||
*/
|
||||
private function addArrayPropertyHelper(&$aProperties, $oArrayProp, $iType)
|
||||
{
|
||||
foreach ($oArrayProp as $oProp)
|
||||
{
|
||||
$oTypes = $oProp ? $oProp['TYPE'] : null;
|
||||
$aTypes = $oTypes ? $oTypes->getParts() : array();
|
||||
$sValue = $oProp ? \trim($oProp->getValue()) : '';
|
||||
|
||||
if (0 < \strlen($sValue))
|
||||
{
|
||||
if (!$oTypes || $oTypes->has('PREF'))
|
||||
{
|
||||
\array_unshift($aProperties, new Property($iType, $sValue, \implode(',', $aTypes)));
|
||||
}
|
||||
else
|
||||
{
|
||||
\array_push($aProperties, new Property($iType, $sValue, \implode(',', $aTypes)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function PopulateByVCard($sVCard, $sEtag = '')
|
||||
{
|
||||
$this->Properties = array();
|
||||
|
||||
if (!\class_exists('Sabre\DAV\Client'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($sEtag))
|
||||
{
|
||||
$this->Etag = $sEtag;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$oVCard = \Sabre\VObject\Reader::read($sVCard);
|
||||
}
|
||||
catch (\Exception $oExc) {};
|
||||
|
||||
$aProperties = array();
|
||||
if ($oVCard)
|
||||
{
|
||||
$bOldVersion = empty($oVCard->VERSION) ? false :
|
||||
\in_array((string) $oVCard->VERSION, array('2.1', '2.0', '1.0'));
|
||||
|
||||
$this->IdContactStr = $oVCard->UID ? (string) $oVCard->UID : \Sabre\DAV\UUIDUtil::getUUID();
|
||||
|
||||
if (isset($oVCard->FN) && '' !== \trim($oVCard->FN))
|
||||
{
|
||||
$sValue = $this->getPropertyValueHelper($oVCard->FN, $bOldVersion);
|
||||
$aProperties[] = new Property(PropertyType::FULLNAME, $sValue);
|
||||
}
|
||||
|
||||
if (isset($oVCard->NICKNAME) && '' !== \trim($oVCard->NICKNAME))
|
||||
{
|
||||
$sValue = $sValue = $this->getPropertyValueHelper($oVCard->NICKNAME, $bOldVersion);
|
||||
$aProperties[] = new Property(PropertyType::NICK_NAME, $sValue);
|
||||
}
|
||||
|
||||
if (isset($oVCard->NOTE) && '' !== \trim($oVCard->NOTE))
|
||||
{
|
||||
$sValue = $this->getPropertyValueHelper($oVCard->NOTE, $bOldVersion);
|
||||
$aProperties[] = new Property(PropertyType::NOTE, $sValue);
|
||||
}
|
||||
|
||||
if (isset($oVCard->N))
|
||||
{
|
||||
$aNames = $oVCard->N->getParts();
|
||||
foreach ($aNames as $iIndex => $sValue)
|
||||
{
|
||||
$sValue = \trim($sValue);
|
||||
if ($bOldVersion && !isset($oVCard->N->parameters['CHARSET']))
|
||||
{
|
||||
if (0 < \strlen($sValue))
|
||||
{
|
||||
$sEncValue = @\utf8_encode($sValue);
|
||||
if (0 === \strlen($sEncValue))
|
||||
{
|
||||
$sEncValue = $sValue;
|
||||
}
|
||||
|
||||
$sValue = $sEncValue;
|
||||
}
|
||||
}
|
||||
|
||||
$sValue = \MailSo\Base\Utils::Utf8Clear($sValue);
|
||||
switch ($iIndex) {
|
||||
case 0:
|
||||
$aProperties[] = new Property(PropertyType::LAST_NAME, $sValue);
|
||||
break;
|
||||
case 1:
|
||||
$aProperties[] = new Property(PropertyType::FIRST_NAME, $sValue);
|
||||
break;
|
||||
case 2:
|
||||
$aProperties[] = new Property(PropertyType::MIDDLE_NAME, $sValue);
|
||||
break;
|
||||
case 3:
|
||||
$aProperties[] = new Property(PropertyType::NAME_PREFIX, $sValue);
|
||||
break;
|
||||
case 4:
|
||||
$aProperties[] = new Property(PropertyType::NAME_SUFFIX, $sValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($oVCard->EMAIL))
|
||||
{
|
||||
$this->addArrayPropertyHelper($aProperties, $oVCard->EMAIL, PropertyType::EMAIl);
|
||||
}
|
||||
|
||||
if (isset($oVCard->URL))
|
||||
{
|
||||
$this->addArrayPropertyHelper($aProperties, $oVCard->URL, PropertyType::WEB_PAGE);
|
||||
}
|
||||
|
||||
if (isset($oVCard->TEL))
|
||||
{
|
||||
$this->addArrayPropertyHelper($aProperties, $oVCard->TEL, PropertyType::PHONE);
|
||||
}
|
||||
|
||||
$this->Properties = $aProperties;
|
||||
}
|
||||
|
||||
$this->UpdateDependentValues();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\AddressBook\Classes;
|
||||
|
||||
use RainLoop\Providers\AddressBook\Enumerations\PropertyType;
|
||||
|
||||
class Property
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $IdProperty;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $Type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $TypeStr;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $Value;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $ValueCustom;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $Frec;
|
||||
|
||||
public function __construct(
|
||||
$iType = \RainLoop\Providers\AddressBook\Enumerations\PropertyType::UNKNOWN, $sValue = '', $sTypeStr = '')
|
||||
{
|
||||
$this->Clear();
|
||||
|
||||
$this->Type = $iType;
|
||||
$this->Value = $sValue;
|
||||
$this->TypeStr = $sTypeStr;
|
||||
}
|
||||
|
||||
public function Clear()
|
||||
{
|
||||
$this->IdProperty = 0;
|
||||
|
||||
$this->Type = PropertyType::UNKNOWN;
|
||||
$this->TypeStr = '';
|
||||
|
||||
$this->Value = '';
|
||||
$this->ValueCustom = '';
|
||||
|
||||
$this->Frec = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsEmail()
|
||||
{
|
||||
return PropertyType::EMAIl === $this->Type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsPhone()
|
||||
{
|
||||
return PropertyType::PHONE === $this->Type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsWeb()
|
||||
{
|
||||
return PropertyType::WEB_PAGE === $this->Type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function TypesAsArray()
|
||||
{
|
||||
$aResult = array();
|
||||
if (!empty($this->TypeStr))
|
||||
{
|
||||
$sTypeStr = \preg_replace('/[\s]+/', '', $this->TypeStr);
|
||||
$aResult = \explode(',', $sTypeStr);
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function TypesUpperAsArray()
|
||||
{
|
||||
return \array_map('strtoupper', $this->TypesAsArray());
|
||||
}
|
||||
|
||||
public function UpdateDependentValues()
|
||||
{
|
||||
$this->Value = \trim($this->Value);
|
||||
$this->ValueCustom = \trim($this->ValueCustom);
|
||||
$this->TypeStr = \trim($this->TypeStr);
|
||||
|
||||
if (0 < \strlen($this->Value))
|
||||
{
|
||||
// lower
|
||||
if ($this->IsEmail())
|
||||
{
|
||||
$this->Value = \MailSo\Base\Utils::StrToLowerIfAscii($this->Value);
|
||||
}
|
||||
|
||||
// phones clear value for searching
|
||||
if ($this->IsPhone())
|
||||
{
|
||||
$sPhone = $this->Value;
|
||||
$sPhone = \preg_replace('/^[+]+/', '', $sPhone);
|
||||
$sPhone = \preg_replace('/[^\d]/', '', $sPhone);
|
||||
$this->ValueCustom = $sPhone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\AddressBook\Classes;
|
||||
|
||||
class Tag
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $IdContactTag;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $Name;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $ReadOnly;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->Clear();
|
||||
}
|
||||
|
||||
public function Clear()
|
||||
{
|
||||
$this->IdContactTag = '';
|
||||
$this->Name = '';
|
||||
$this->ReadOnly = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\AddressBook\Enumerations;
|
||||
|
||||
class PropertyType
|
||||
{
|
||||
const UNKNOWN = 0;
|
||||
|
||||
const FULLNAME = 10;
|
||||
|
||||
const FIRST_NAME = 15;
|
||||
const LAST_NAME = 16;
|
||||
const MIDDLE_NAME = 17;
|
||||
const NICK_NAME = 18;
|
||||
|
||||
const NAME_PREFIX = 20;
|
||||
const NAME_SUFFIX = 21;
|
||||
|
||||
const EMAIl = 30;
|
||||
const PHONE = 31;
|
||||
// const MOBILE = 32;
|
||||
// const FAX = 33;
|
||||
const WEB_PAGE = 32;
|
||||
|
||||
const BIRTHDAY = 40;
|
||||
|
||||
const FACEBOOK = 90;
|
||||
const SKYPE = 91;
|
||||
const GITHUB = 92;
|
||||
|
||||
const NOTE = 110;
|
||||
|
||||
const CUSTOM = 250;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class ChangePassword extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Actions
|
||||
*/
|
||||
private $oActions;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Providers\ChangePassword\ChangePasswordInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bCheckWeak;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Actions $oActions
|
||||
* @param \RainLoop\Providers\ChangePassword\ChangePasswordInterface|null $oDriver = null
|
||||
* @param bool $bCheckWeak = true
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($oActions, $oDriver = null, $bCheckWeak = true)
|
||||
{
|
||||
$this->oActions = $oActions;
|
||||
$this->oDriver = $oDriver;
|
||||
$this->bCheckWeak = !!$bCheckWeak;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function PasswordChangePossibility($oAccount)
|
||||
{
|
||||
return $this->IsActive() &&
|
||||
$oAccount instanceof \RainLoop\Account &&
|
||||
$this->oDriver && $this->oDriver->PasswordChangePossibility($oAccount)
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sPrevPassword
|
||||
* @param string $sNewPassword
|
||||
*/
|
||||
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
|
||||
{
|
||||
if ($this->oDriver instanceof \RainLoop\Providers\ChangePassword\ChangePasswordInterface &&
|
||||
$this->PasswordChangePossibility($oAccount))
|
||||
{
|
||||
if ($sPrevPassword !== $oAccount->Password())
|
||||
{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CurrentPasswordIncorrect);
|
||||
}
|
||||
|
||||
$sPasswordForCheck = \trim($sNewPassword);
|
||||
if (6 > \strlen($sPasswordForCheck))
|
||||
{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::NewPasswordShort);
|
||||
}
|
||||
|
||||
if (!\MailSo\Base\Utils::PasswordWeaknessCheck($sPasswordForCheck))
|
||||
{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::NewPasswordWeak);
|
||||
}
|
||||
|
||||
if (!$this->oDriver->ChangePassword($oAccount, $sPrevPassword, $sNewPassword))
|
||||
{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CouldNotSaveNewPassword);
|
||||
}
|
||||
|
||||
$oAccount->SetPassword($sNewPassword);
|
||||
$this->oActions->SetAuthToken($oAccount);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CouldNotSaveNewPassword);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\ChangePassword\ChangePasswordInterface;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\ChangePassword;
|
||||
|
||||
interface ChangePasswordInterface
|
||||
{
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function PasswordChangePossibility($oAccount);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sPrevPassword
|
||||
* @param string $sNewPassword
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword);
|
||||
}
|
||||
188
rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Domain.php
Normal file
188
rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Domain.php
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class Domain extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\Domain\DomainInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Plugins\Manager
|
||||
*/
|
||||
private $oPlugins;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bAdmin;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\Domain\DomainInterface $oDriver
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(\RainLoop\Providers\Domain\DomainInterface $oDriver,
|
||||
\RainLoop\Plugins\Manager $oPlugins)
|
||||
{
|
||||
$this->oDriver = $oDriver;
|
||||
$this->oPlugins = $oPlugins;
|
||||
$this->bAdmin = $this->oDriver instanceof \RainLoop\Providers\Domain\DomainAdminInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAdmin()
|
||||
{
|
||||
return $this->bAdmin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bFindWithWildCard = false
|
||||
* @param bool $bCheckDisabled = true
|
||||
*
|
||||
* @return \RainLoop\Model\Domain|null
|
||||
*/
|
||||
public function Load($sName, $bFindWithWildCard = false, $bCheckDisabled = true)
|
||||
{
|
||||
$oDomain = $this->oDriver->Load($sName, $bFindWithWildCard, $bCheckDisabled);
|
||||
if ($oDomain instanceof \RainLoop\Model\Domain)
|
||||
{
|
||||
$this->oPlugins->RunHook('filter.domain', array(&$oDomain));
|
||||
}
|
||||
|
||||
return $oDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Domain $oDomain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save(\RainLoop\Model\Domain $oDomain)
|
||||
{
|
||||
return $this->bAdmin ? $this->oDriver->Save($oDomain) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Delete($sName)
|
||||
{
|
||||
return $this->bAdmin ? $this->oDriver->Delete($sName) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bDisabled
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Disable($sName, $bDisabled)
|
||||
{
|
||||
return $this->bAdmin ? $this->oDriver->Disable($sName, $bDisabled) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iOffset = 0
|
||||
* @param int $iLimit = 20
|
||||
* @param string $sSearch = ''
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetList($iOffset = 0, $iLimit = 20, $sSearch = '')
|
||||
{
|
||||
return $this->bAdmin ? $this->oDriver->GetList($iOffset, $iLimit, $sSearch) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch = ''
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function Count($sSearch = '')
|
||||
{
|
||||
return $this->oDriver->Count($sSearch);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Actions $oActions
|
||||
* @param string $sNameForTest = ''
|
||||
*
|
||||
* @return \RainLoop\Model\Domain | null
|
||||
*/
|
||||
public function LoadOrCreateNewFromAction(\RainLoop\Actions $oActions, $sNameForTest = '')
|
||||
{
|
||||
$oDomain = null;
|
||||
|
||||
if ($this->bAdmin)
|
||||
{
|
||||
$bCreate = '1' === (string) $oActions->GetActionParam('Create', '0');
|
||||
$sName = (string) $oActions->GetActionParam('Name', '');
|
||||
$sIncHost = (string) $oActions->GetActionParam('IncHost', '');
|
||||
$iIncPort = (int) $oActions->GetActionParam('IncPort', 143);
|
||||
$iIncSecure = (int) $oActions->GetActionParam('IncSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE);
|
||||
$bIncShortLogin = '1' === (string) $oActions->GetActionParam('IncShortLogin', '0');
|
||||
$bUseSieve = '1' === (string) $oActions->GetActionParam('UseSieve', '0');
|
||||
$sSieveHost = (string) $oActions->GetActionParam('SieveHost', '');
|
||||
$iSievePort = (int) $oActions->GetActionParam('SievePort', 2000);
|
||||
$iSieveSecure = (int) $oActions->GetActionParam('SieveSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE);
|
||||
$sOutHost = (string) $oActions->GetActionParam('OutHost', '');
|
||||
$iOutPort = (int) $oActions->GetActionParam('OutPort', 25);
|
||||
$iOutSecure = (int) $oActions->GetActionParam('OutSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE);
|
||||
$bOutShortLogin = '1' === (string) $oActions->GetActionParam('OutShortLogin', '0');
|
||||
$bOutAuth = '1' === (string) $oActions->GetActionParam('OutAuth', '1');
|
||||
$bOutUsePhpMail = '1' === (string) $oActions->GetActionParam('OutUsePhpMail', '0');
|
||||
$sWhiteList = (string) $oActions->GetActionParam('WhiteList', '');
|
||||
|
||||
if (0 < \strlen($sName) && 0 < strlen($sNameForTest) && false === \strpos($sName, '*'))
|
||||
{
|
||||
$sNameForTest = '';
|
||||
}
|
||||
|
||||
if (0 < strlen($sName) || 0 < strlen($sNameForTest))
|
||||
{
|
||||
$oDomain = 0 < strlen($sNameForTest) ? null : $this->Load($sName);
|
||||
if ($oDomain instanceof \RainLoop\Model\Domain)
|
||||
{
|
||||
if ($bCreate)
|
||||
{
|
||||
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DomainAlreadyExists);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDomain->UpdateInstance(
|
||||
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
|
||||
$bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
|
||||
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
|
||||
$sWhiteList);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$oDomain = \RainLoop\Model\Domain::NewInstance(0 < strlen($sNameForTest) ? $sNameForTest : $sName,
|
||||
$sIncHost, $iIncPort, $iIncSecure, $bIncShortLogin,
|
||||
$bUseSieve, $sSieveHost, $iSievePort, $iSieveSecure,
|
||||
$sOutHost, $iOutPort, $iOutSecure, $bOutShortLogin, $bOutAuth, $bOutUsePhpMail,
|
||||
$sWhiteList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $oDomain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\Domain\DomainInterface;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,332 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Domain;
|
||||
|
||||
class DefaultDomain implements \RainLoop\Providers\Domain\DomainAdminInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $sDomainPath;
|
||||
|
||||
/**
|
||||
* @var \MailSo\Cache\CacheClient
|
||||
*/
|
||||
protected $oCacher;
|
||||
|
||||
/**
|
||||
* @param string $sDomainPath
|
||||
* @param \MailSo\Cache\CacheClient $oCacher = null
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sDomainPath, $oCacher = null)
|
||||
{
|
||||
$this->sDomainPath = \rtrim(\trim($sDomainPath), '\\/');
|
||||
$this->oCacher = $oCacher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bBack = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function codeFileName($sName, $bBack = false)
|
||||
{
|
||||
if ($bBack && 'default' === $sName)
|
||||
{
|
||||
return '*';
|
||||
}
|
||||
else if (!$bBack && '*' === $sName)
|
||||
{
|
||||
return 'default';
|
||||
}
|
||||
|
||||
if ($bBack)
|
||||
{
|
||||
$sName = \MailSo\Base\Utils::IdnToUtf8($sName, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sName = \MailSo\Base\Utils::IdnToAscii($sName, true);
|
||||
}
|
||||
|
||||
return $bBack ? \str_replace('_wildcard_', '*', $sName) : \str_replace('*', '_wildcard_', $sName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bDisable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Disable($sName, $bDisable)
|
||||
{
|
||||
$sName = \MailSo\Base\Utils::IdnToAscii($sName, true);
|
||||
|
||||
$sFile = '';
|
||||
if (\file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sFile = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
}
|
||||
|
||||
$aResult = array();
|
||||
$aNames = \explode(',', $sFile);
|
||||
if ($bDisable)
|
||||
{
|
||||
\array_push($aNames, $sName);
|
||||
$aResult = $aNames;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($aNames as $sItem)
|
||||
{
|
||||
if ($sName !== $sItem)
|
||||
{
|
||||
$aResult[] = $sItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aResult = \array_unique($aResult);
|
||||
return false !== \file_put_contents($this->sDomainPath.'/disabled', \trim(\implode(',', $aResult), ', '));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function wildcardDomainsCacheKey()
|
||||
{
|
||||
return '/WildCard/DomainCache/'.\md5(APP_VERSION.APP_PRIVATE_DATA_NAME).'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getWildcardDomainsLine()
|
||||
{
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$sResult = $this->oCacher->Get($this->wildcardDomainsCacheKey());
|
||||
if (0 < \strlen($sResult))
|
||||
{
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
|
||||
$sResult = '';
|
||||
$aNames = array();
|
||||
|
||||
$aList = \glob($this->sDomainPath.'/*.ini');
|
||||
foreach ($aList as $sFile)
|
||||
{
|
||||
$sName = \substr(\basename($sFile), 0, -4);
|
||||
if ('default' === $sName || false !== \strpos($sName, '_wildcard_'))
|
||||
{
|
||||
$aNames[] = $this->codeFileName($sName, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < \count($aNames))
|
||||
{
|
||||
\rsort($aNames, SORT_STRING);
|
||||
$sResult = \implode(' ', $aNames);
|
||||
}
|
||||
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$this->oCacher->Set($this->wildcardDomainsCacheKey(), $sResult);
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bFindWithWildCard = false
|
||||
* @param bool $bCheckDisabled = true
|
||||
*
|
||||
* @return \RainLoop\Model\Domain|null
|
||||
*/
|
||||
public function Load($sName, $bFindWithWildCard = false, $bCheckDisabled = true)
|
||||
{
|
||||
$mResult = null;
|
||||
|
||||
$sDisabled = '';
|
||||
$sFoundedValue = '';
|
||||
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if (\file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sDisabled = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
}
|
||||
|
||||
if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini') &&
|
||||
(!$bCheckDisabled || 0 === \strlen($sDisabled) || false === \strpos(','.$sDisabled.',', ','.\MailSo\Base\Utils::IdnToAscii($sName, true).',')))
|
||||
{
|
||||
$aDomain = \RainLoop\Utils::CustomParseIniFile($this->sDomainPath.'/'.$sRealFileName.'.ini');
|
||||
// fix misspellings (#119)
|
||||
if (\is_array($aDomain))
|
||||
{
|
||||
if (isset($aDomain['smpt_host']))
|
||||
{
|
||||
$aDomain['smtp_host'] = $aDomain['smpt_host'];
|
||||
}
|
||||
|
||||
if (isset($aDomain['smpt_port']))
|
||||
{
|
||||
$aDomain['smtp_port'] = $aDomain['smpt_port'];
|
||||
}
|
||||
|
||||
if (isset($aDomain['smpt_secure']))
|
||||
{
|
||||
$aDomain['smtp_secure'] = $aDomain['smpt_secure'];
|
||||
}
|
||||
|
||||
if (isset($aDomain['smpt_auth']))
|
||||
{
|
||||
$aDomain['smtp_auth'] = $aDomain['smpt_auth'];
|
||||
}
|
||||
}
|
||||
//---
|
||||
|
||||
$mResult = \RainLoop\Model\Domain::NewInstanceFromDomainConfigArray($sName, $aDomain);
|
||||
}
|
||||
else if ($bFindWithWildCard)
|
||||
{
|
||||
$sNames = $this->getWildcardDomainsLine();
|
||||
if (0 < \strlen($sNames))
|
||||
{
|
||||
if (\RainLoop\Plugins\Helper::ValidateWildcardValues(
|
||||
\MailSo\Base\Utils::IdnToUtf8($sName, true), $sNames, $sFoundedValue) && 0 < \strlen($sFoundedValue))
|
||||
{
|
||||
if (!$bCheckDisabled || 0 === \strlen($sDisabled) || false === \strpos(','.$sDisabled.',', ','.$sFoundedValue.','))
|
||||
{
|
||||
$mResult = $this->Load($sFoundedValue, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Domain $oDomain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save(\RainLoop\Model\Domain $oDomain)
|
||||
{
|
||||
$sRealFileName = $this->codeFileName($oDomain->Name());
|
||||
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$this->oCacher->Delete($this->wildcardDomainsCacheKey());
|
||||
}
|
||||
|
||||
$mResult = \file_put_contents($this->sDomainPath.'/'.$sRealFileName.'.ini', $oDomain->ToIniString());
|
||||
return \is_int($mResult) && 0 < $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Delete($sName)
|
||||
{
|
||||
$bResult = true;
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if (0 < \strlen($sName) && \file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini'))
|
||||
{
|
||||
$bResult = \unlink($this->sDomainPath.'/'.$sRealFileName.'.ini');
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
{
|
||||
$this->Disable($sName, false);
|
||||
}
|
||||
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$this->oCacher->Delete($this->wildcardDomainsCacheKey());
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iOffset
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetList($iOffset, $iLimit = 20)
|
||||
{
|
||||
$aResult = array();
|
||||
$aWildCards = array();
|
||||
$aList = \glob($this->sDomainPath.'/*.ini');
|
||||
|
||||
foreach ($aList as $sFile)
|
||||
{
|
||||
$sName = \substr(\basename($sFile), 0, -4);
|
||||
$sName = $this->codeFileName($sName, true);
|
||||
|
||||
if (false === \strpos($sName, '*'))
|
||||
{
|
||||
$aResult[] = $sName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aWildCards[] = $sName;
|
||||
}
|
||||
}
|
||||
|
||||
\sort($aResult, SORT_STRING);
|
||||
\rsort($aWildCards, SORT_STRING);
|
||||
|
||||
$aResult = \array_merge($aResult, $aWildCards);
|
||||
|
||||
$iOffset = (0 > $iOffset) ? 0 : $iOffset;
|
||||
$iLimit = (0 > $iLimit) ? 0 : ((999 < $iLimit) ? 999 : $iLimit);
|
||||
|
||||
$aResult = \array_slice($aResult, $iOffset, $iLimit);
|
||||
|
||||
$aDisabledNames = array();
|
||||
if (0 < \count($aResult) && \file_exists($this->sDomainPath.'/disabled'))
|
||||
{
|
||||
$sDisabled = @\file_get_contents($this->sDomainPath.'/disabled');
|
||||
if (false !== $sDisabled && 0 < strlen($sDisabled))
|
||||
{
|
||||
$aDisabledNames = \explode(',', $sDisabled);
|
||||
$aDisabledNames = \array_unique($aDisabledNames);
|
||||
foreach ($aDisabledNames as $iIndex => $sValue)
|
||||
{
|
||||
$aDisabledNames[$iIndex] = \MailSo\Base\Utils::IdnToUtf8($sValue, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aReturn = array();
|
||||
foreach ($aResult as $sName)
|
||||
{
|
||||
$aReturn[$sName] = !\in_array($sName, $aDisabledNames);
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch = ''
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function Count()
|
||||
{
|
||||
return \count($this->GetList(0, 999));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Domain;
|
||||
|
||||
interface DomainAdminInterface extends DomainInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bDisable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Disable($sName, $bDisable);
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param bool $bFindWithWildCard = false
|
||||
* @param bool $bCheckDisabled = true
|
||||
*
|
||||
* @return \RainLoop\Model\Domain|null
|
||||
*/
|
||||
public function Load($sName, $bFindWithWildCard = false, $bCheckDisabled = true);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Domain $oDomain
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save(\RainLoop\Model\Domain $oDomain);
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Delete($sName);
|
||||
|
||||
/**
|
||||
* @param int $iOffset
|
||||
* @param int $iLimit = 20
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetList($iOffset, $iLimit = 20);
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function Count();
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Domain;
|
||||
|
||||
interface DomainInterface
|
||||
{
|
||||
}
|
||||
117
rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php
Normal file
117
rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Files.php
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class Files extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\Files\FilesInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(\RainLoop\Providers\Files\FilesInterface $oDriver)
|
||||
{
|
||||
$this->oDriver = $oDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param resource $rSource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function PutFile($oAccount, $sKey, $rSource)
|
||||
{
|
||||
return $this->oDriver->PutFile($oAccount, $sKey, $rSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param string $sSource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function MoveUploadedFile($oAccount, $sKey, $sSource)
|
||||
{
|
||||
return $this->oDriver->MoveUploadedFile($oAccount, $sKey, $sSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param string $sOpenMode = 'rb'
|
||||
*
|
||||
* @return resource|bool
|
||||
*/
|
||||
public function GetFile($oAccount, $sKey, $sOpenMode = 'rb')
|
||||
{
|
||||
return $this->oDriver->GetFile($oAccount, $sKey, $sOpenMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string | bool
|
||||
*/
|
||||
public function GetFileName($oAccount, $sKey)
|
||||
{
|
||||
return $this->oDriver->GetFileName($oAccount, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Clear($oAccount, $sKey)
|
||||
{
|
||||
return $this->oDriver->Clear($oAccount, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return int|bool
|
||||
*/
|
||||
public function FileSize($oAccount, $sKey)
|
||||
{
|
||||
return $this->oDriver->FileSize($oAccount, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function FileExists($oAccount, $sKey)
|
||||
{
|
||||
return $this->oDriver->FileExists($oAccount, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iTimeToClearInHours = 24
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function GC($iTimeToClearInHours = 24)
|
||||
{
|
||||
return $this->oDriver ? $this->oDriver->GC($iTimeToClearInHours) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\Files\FilesInterface;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Files;
|
||||
|
||||
class DefaultStorage implements \RainLoop\Providers\Files\FilesInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDataPath;
|
||||
|
||||
/**
|
||||
* @param string $sStoragePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sStoragePath)
|
||||
{
|
||||
$this->sDataPath = \rtrim(\trim($sStoragePath), '\\/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param resource $rSource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function PutFile($oAccount, $sKey, $rSource)
|
||||
{
|
||||
$bResult = false;
|
||||
if ($rSource)
|
||||
{
|
||||
$rOpenOutput = @\fopen($this->generateFileName($oAccount, $sKey, true), 'w+b');
|
||||
if ($rOpenOutput)
|
||||
{
|
||||
$bResult = (false !== \MailSo\Base\Utils::MultipleStreamWriter($rSource, array($rOpenOutput)));
|
||||
@\fclose($rOpenOutput);
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param string $sSource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function MoveUploadedFile($oAccount, $sKey, $sSource)
|
||||
{
|
||||
return @\move_uploaded_file($sSource,
|
||||
$this->generateFileName($oAccount, $sKey, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param string $sOpenMode = 'rb'
|
||||
*
|
||||
* @return resource|bool
|
||||
*/
|
||||
public function GetFile($oAccount, $sKey, $sOpenMode = 'rb')
|
||||
{
|
||||
$mResult = false;
|
||||
$bCreate = !!\preg_match('/[wac]/', $sOpenMode);
|
||||
|
||||
$sFileName = $this->generateFileName($oAccount, $sKey, $bCreate);
|
||||
if ($bCreate || \file_exists($sFileName))
|
||||
{
|
||||
$mResult = @\fopen($sFileName, $sOpenMode);
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function GetFileName($oAccount, $sKey)
|
||||
{
|
||||
$mResult = false;
|
||||
$sFileName = $this->generateFileName($oAccount, $sKey);
|
||||
if (\file_exists($sFileName))
|
||||
{
|
||||
$mResult = $sFileName;
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Clear($oAccount, $sKey)
|
||||
{
|
||||
$mResult = true;
|
||||
$sFileName = $this->generateFileName($oAccount, $sKey);
|
||||
if (\file_exists($sFileName))
|
||||
{
|
||||
$mResult = @\unlink($sFileName);
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return int|bool
|
||||
*/
|
||||
public function FileSize($oAccount, $sKey)
|
||||
{
|
||||
$mResult = false;
|
||||
$sFileName = $this->generateFileName($oAccount, $sKey);
|
||||
if (\file_exists($sFileName))
|
||||
{
|
||||
$mResult = \filesize($sFileName);
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function FileExists($oAccount, $sKey)
|
||||
{
|
||||
return @\file_exists($this->generateFileName($oAccount, $sKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iTimeToClearInHours = 24
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function GC($iTimeToClearInHours = 24)
|
||||
{
|
||||
if (0 < $iTimeToClearInHours)
|
||||
{
|
||||
\MailSo\Base\Utils::RecTimeDirRemove($this->sDataPath, 60 * 60 * $iTimeToClearInHours, \time());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param bool $bMkDir = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generateFileName($oAccount, $sKey, $bMkDir = false)
|
||||
{
|
||||
$sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_',
|
||||
('' === $oAccount->ParentEmail() ? '' : $oAccount->ParentEmail().'/').$oAccount->Email());
|
||||
|
||||
$sKeyPath = \sha1($sKey);
|
||||
$sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath;
|
||||
|
||||
$sFilePath = $this->sDataPath.'/'.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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Files;
|
||||
|
||||
interface FilesInterface
|
||||
{
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param resource $rSource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function PutFile($oAccount, $sKey, $rSource);
|
||||
|
||||
/**
|
||||
* @param CAccount $oAccount
|
||||
* @param string $sKey
|
||||
* @param string $sSource
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function MoveUploadedFile($oAccount, $sKey, $sSource);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
* @param string $sOpenMode = 'rb'
|
||||
*
|
||||
* @return resource|bool
|
||||
*/
|
||||
public function GetFile($oAccount, $sKey, $sOpenMode = 'rb');
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function GetFileName($oAccount, $sKey);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Clear($oAccount, $sKey);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return int | bool
|
||||
*/
|
||||
public function FileSize($oAccount, $sKey);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function FileExists($oAccount, $sKey);
|
||||
|
||||
/**
|
||||
* @param int $iTimeToClearInHours = 24
|
||||
|
||||
* @return bool
|
||||
*/
|
||||
public function GC($iTimeToClearInHours = 24);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class Filters extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\Filters\FiltersInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($oDriver)
|
||||
{
|
||||
$this->oDriver = $oDriver instanceof \RainLoop\Providers\Filters\FiltersInterface ? $oDriver : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function Load()
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->Load() : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aFilters
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($aFilters)
|
||||
{
|
||||
return $this->IsActive() ? $this->oDriver->Save($aFilters) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\Filters\FiltersInterface;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters\Classes;
|
||||
|
||||
class Filter
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sID;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sName;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $aConditions;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sActionType;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sActionValue;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bMarkAsRead;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $bSkipOthers;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->Clear();
|
||||
}
|
||||
|
||||
public function Clear()
|
||||
{
|
||||
$this->sID = '';
|
||||
$this->sName = '';
|
||||
|
||||
$this->aConditions = array();
|
||||
|
||||
$this->sFilterRulesType = \RainLoop\Providers\Filters\Enumerations\FilterRulesType::ALL;
|
||||
|
||||
$this->sActionType = \RainLoop\Providers\Filters\Enumerations\ActionType::MOVE_TO;
|
||||
$this->sActionValue = '';
|
||||
|
||||
$this->bMarkAsRead = false;
|
||||
$this->bSkipOthers = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ID()
|
||||
{
|
||||
return $this->sID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Name()
|
||||
{
|
||||
return $this->sName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function Conditions()
|
||||
{
|
||||
return $this->aConditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function FilterRulesType()
|
||||
{
|
||||
return $this->sFilterRulesType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ActionType()
|
||||
{
|
||||
return $this->sActionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ActionValue()
|
||||
{
|
||||
return $this->sActionValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function MarkAsRead()
|
||||
{
|
||||
return $this->bMarkAsRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function SkipOthers()
|
||||
{
|
||||
return $this->bSkipOthers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function serializeToJson()
|
||||
{
|
||||
return \json_encode($this->ToSimpleJSON());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFilterJson
|
||||
*/
|
||||
public function unserializeFromJson($sFilterJson)
|
||||
{
|
||||
$sFilterJson = \json_decode(\trim($sFilterJson));
|
||||
if (!empty($sFilterJson))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aFilter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function FromJSON($aFilter)
|
||||
{
|
||||
if (\is_array($aFilter))
|
||||
{
|
||||
$this->sID = isset($aFilter['ID']) ? $aFilter['ID'] : '';
|
||||
$this->sName = isset($aFilter['Name']) ? $aFilter['Name'] : '';
|
||||
|
||||
$this->sFilterRulesType = isset($aFilter['FilterRulesType']) ? $aFilter['FilterRulesType'] :
|
||||
\RainLoop\Providers\Filters\Enumerations\FilterRulesType::ALL;
|
||||
|
||||
$this->sActionType = isset($aFilter['ActionType']) ? $aFilter['ActionType'] :
|
||||
\RainLoop\Providers\Filters\Enumerations\ActionType::MOVE_TO;
|
||||
|
||||
$this->sActionValue = isset($aFilter['ActionValue']) ? $aFilter['ActionValue'] : '';
|
||||
|
||||
$this->bMarkAsRead = isset($aFilter['MarkAsRead']) ? $aFilter['MarkAsRead'] : false;
|
||||
$this->bSkipOthers = isset($aFilter['SkipOthers']) ? $aFilter['SkipOthers'] : false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAjax = false
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ToSimpleJSON($bAjax = false)
|
||||
{
|
||||
$aConditions = array();
|
||||
foreach ($this->Conditions() as $oItem)
|
||||
{
|
||||
if ($oItem)
|
||||
{
|
||||
$aConditions[] = $oItem->ToSimpleJSON($bAjax);
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'ID' => $this->ID(),
|
||||
'Name' => $this->Name(),
|
||||
'Conditions' => $aConditions,
|
||||
'FilterRulesType' => $this->FilterRulesType(),
|
||||
'ActionType' => $this->ActionType(),
|
||||
'ActionValue' => $this->ActionValue(),
|
||||
'MarkAsRead' => $this->MarkAsRead(),
|
||||
'SkipOthers' => $this->SkipOthers()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters\Classes;
|
||||
|
||||
class FilterCondition
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sField;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sType;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sValue;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->Clear();
|
||||
}
|
||||
|
||||
public function Clear()
|
||||
{
|
||||
$this->sField = \RainLoop\Providers\Filters\Enumerations\ConditionField::FROM;
|
||||
$this->sType = \RainLoop\Providers\Filters\Enumerations\ConditionType::EQUAL_TO;
|
||||
$this->sValue = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Field()
|
||||
{
|
||||
return $this->sField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Type()
|
||||
{
|
||||
return $this->sType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Value()
|
||||
{
|
||||
return $this->sValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aFilter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function FromJSON($aFilter)
|
||||
{
|
||||
if (\is_array($aFilter))
|
||||
{
|
||||
$this->sField = isset($aFilter['Field']) ? $aFilter['Field'] :
|
||||
\RainLoop\Providers\Filters\Enumerations\ConditionField::FROM;
|
||||
|
||||
$this->sType = isset($aFilter['Type']) ? $aFilter['Type'] :
|
||||
\RainLoop\Providers\Filters\Enumerations\ConditionType::EQUAL_TO;
|
||||
|
||||
$this->sValue = isset($aFilter['Value']) ? $aFilter['Value'] : '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAjax = false
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ToSimpleJSON($bAjax = false)
|
||||
{
|
||||
return array(
|
||||
'Field' => $this->Field(),
|
||||
'Type' => $this->Type(),
|
||||
'Value' => $this->Value()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters\Enumerations;
|
||||
|
||||
class ActionType
|
||||
{
|
||||
const NONE = 'None';
|
||||
const MOVE_TO = 'MoveTo';
|
||||
const DISCARD = 'Discard';
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters\Enumerations;
|
||||
|
||||
class ConditionField
|
||||
{
|
||||
const FROM = 'From';
|
||||
const RECIPIENT = 'Recipient';
|
||||
const SUBJECT = 'Subject';
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters\Enumerations;
|
||||
|
||||
class ConditionType
|
||||
{
|
||||
const EQUAL_TO = 'EqualTo';
|
||||
const NOT_EQUAL_TO = 'NotEqualTo';
|
||||
const CONTAINS = 'Contains';
|
||||
const NOT_CONTAINS = 'NotContains';
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters\Enumerations;
|
||||
|
||||
class FilterRulesType
|
||||
{
|
||||
const ALL = 'All';
|
||||
const ANY = 'Any';
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters;
|
||||
|
||||
interface FiltersInterface
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function Load();
|
||||
|
||||
/**
|
||||
* @param array $aFilters
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($aFilters);
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Filters;
|
||||
|
||||
class SieveStorage implements \RainLoop\Providers\Filters\FiltersInterface
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function Load()
|
||||
{
|
||||
// TODO
|
||||
return $this->fileStringToCollection(@\file_get_contents('e:/sieve.txt'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aFilters
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($aFilters)
|
||||
{
|
||||
return @\file_put_contents('e:/sieve.txt', $this->collectionToFileString($aFilters));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aFilters
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function collectionToFileString($aFilters)
|
||||
{
|
||||
$aParts = array();
|
||||
|
||||
foreach ($aFilters as /* @var $oItem \RainLoop\Providers\Filters\Classes\Filter */ $oItem)
|
||||
{
|
||||
$sItem = $oItem->serializeToJson();
|
||||
$sItem = \chunk_split(\base64_encode($sItem), 74, "\n");
|
||||
|
||||
$aParts[] = $sItem;
|
||||
}
|
||||
|
||||
return \implode("\n", $aParts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFileString
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function fileStringToCollection($sFileString)
|
||||
{
|
||||
if (!empty($sFileString))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class Settings extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\Settings\SettingsInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\Settings\SettingsInterface $oDriver
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(\RainLoop\Providers\Settings\SettingsInterface $oDriver)
|
||||
{
|
||||
$this->oDriver = $oDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
*
|
||||
* @return \RainLoop\Settings
|
||||
*/
|
||||
public function Load(\RainLoop\Model\Account $oAccount)
|
||||
{
|
||||
$oSettings = new \RainLoop\Settings();
|
||||
$oSettings->InitData($this->oDriver->Load($oAccount));
|
||||
return $oSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param \RainLoop\Settings $oSettings
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save(\RainLoop\Model\Account $oAccount, \RainLoop\Settings $oSettings)
|
||||
{
|
||||
return $this->oDriver->Save($oAccount, $oSettings->DataAsArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ClearByEmail($sEmail)
|
||||
{
|
||||
return $this->oDriver->ClearByEmail($sEmail);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\Settings\SettingsInterface;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Settings;
|
||||
|
||||
class DefaultSettings implements \RainLoop\Providers\Settings\SettingsInterface
|
||||
{
|
||||
const FILE_NAME = 'settings';
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Providers\Storage
|
||||
*/
|
||||
private $oStorageProvider;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\Storage $oStorageProvider
|
||||
*/
|
||||
public function __construct(\RainLoop\Providers\Storage $oStorageProvider)
|
||||
{
|
||||
$this->oStorageProvider = $oStorageProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Load($oAccount)
|
||||
{
|
||||
$sValue = $this->oStorageProvider->Get($oAccount,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||
\RainLoop\Providers\Settings\DefaultSettings::FILE_NAME);
|
||||
|
||||
$aSettings = array();
|
||||
if (\is_string($sValue))
|
||||
{
|
||||
$aData = \json_decode($sValue, true);
|
||||
if (\is_array($aData))
|
||||
{
|
||||
$aSettings = $aData;
|
||||
}
|
||||
}
|
||||
|
||||
return $aSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param array $aSettings
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($oAccount, array $aSettings)
|
||||
{
|
||||
return $this->oStorageProvider->Put($oAccount,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||
\RainLoop\Providers\Settings\DefaultSettings::FILE_NAME,
|
||||
\json_encode($aSettings));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ClearByEmail($sEmail)
|
||||
{
|
||||
return $this->oStorageProvider->Clear($sEmail,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::CONFIG,
|
||||
\RainLoop\Providers\Settings\DefaultSettings::FILE_NAME);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Settings;
|
||||
|
||||
interface SettingsInterface
|
||||
{
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Load($oAccount);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param array $aSettings
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Save($oAccount, array $aSettings);
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function ClearByEmail($sEmail);
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class Storage extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\Storage\StorageInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(\RainLoop\Providers\Storage\StorageInterface $oDriver)
|
||||
{
|
||||
$this->oDriver = $oDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|string|null $oAccount
|
||||
* @param int $iStorageType
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function verifyAccount($oAccount, $iStorageType)
|
||||
{
|
||||
if (\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY !== $iStorageType &&
|
||||
!($oAccount instanceof \RainLoop\Model\Account || \is_string($oAccount)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|string|null $oAccount
|
||||
* @param int $iStorageType
|
||||
* @param string $sKey
|
||||
* @param string $sValue
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Put($oAccount, $iStorageType, $sKey, $sValue)
|
||||
{
|
||||
if (!$this->verifyAccount($oAccount, $iStorageType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->oDriver->Put($oAccount, $iStorageType, $sKey, $sValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|string|null $oAccount
|
||||
* @param int $iStorageType
|
||||
* @param string $sKey
|
||||
* @param mixed $mDefault = false
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function Get($oAccount, $iStorageType, $sKey, $mDefault = false)
|
||||
{
|
||||
if (!$this->verifyAccount($oAccount, $iStorageType))
|
||||
{
|
||||
return $mDefault;
|
||||
}
|
||||
|
||||
return $this->oDriver->Get($oAccount, $iStorageType, $sKey, $mDefault);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|string|null $oAccount
|
||||
* @param int $iStorageType
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Clear($oAccount, $iStorageType, $sKey)
|
||||
{
|
||||
if (!$this->verifyAccount($oAccount, $iStorageType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->oDriver->Clear($oAccount, $iStorageType, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\Storage\StorageInterface;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Storage;
|
||||
|
||||
class DefaultStorage implements \RainLoop\Providers\Storage\StorageInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDataPath;
|
||||
|
||||
/**
|
||||
* @param string $sStoragePath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($sStoragePath)
|
||||
{
|
||||
$this->sDataPath = \rtrim(\trim($sStoragePath), '\\/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|string|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\Model\Account|string|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\Model\Account|string|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\Model\Account|string|null $mAccount
|
||||
* @param int $iStorageType
|
||||
* @param string $sKey
|
||||
* @param bool $bMkDir = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generateFileName($mAccount, $iStorageType, $sKey, $bMkDir = false)
|
||||
{
|
||||
if (null === $mAccount)
|
||||
{
|
||||
$iStorageType = \RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY;
|
||||
}
|
||||
|
||||
$sEmail = $mAccount instanceof \RainLoop\Model\Account ? \preg_replace('/[^a-z0-9\-\.@]+/', '_',
|
||||
('' === $mAccount->ParentEmail() ? '' : $mAccount->ParentEmail().'/').$mAccount->Email()) : '';
|
||||
|
||||
if (\is_string($mAccount) && empty($sEmail))
|
||||
{
|
||||
$sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $mAccount);
|
||||
}
|
||||
|
||||
$sTypePath = $sKeyPath = '';
|
||||
switch ($iStorageType)
|
||||
{
|
||||
default:
|
||||
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;
|
||||
}
|
||||
|
||||
$sFilePath = '';
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Storage\Enumerations;
|
||||
|
||||
class StorageType
|
||||
{
|
||||
const USER = 1;
|
||||
const CONFIG = 2;
|
||||
const NOBODY = 3;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Storage;
|
||||
|
||||
interface StorageInterface
|
||||
{
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|null $oAccount
|
||||
* @param int $iStorageType
|
||||
* @param string $sKey
|
||||
* @param string $sValue
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Put($oAccount, $iStorageType, $sKey, $sValue);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|null $oAccount
|
||||
* @param int $iStorageType
|
||||
* @param string $sKey
|
||||
* @param mixed $mDefault = false
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function Get($oAccount, $iStorageType, $sKey, $mDefault = false);
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|null $oAccount
|
||||
* @param int $iStorageType
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Clear($oAccount, $iStorageType, $sKey);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class Suggestions extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\Suggestions\SuggestionsInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\Suggestions\SuggestionsInterface|null $oDriver = null
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($oDriver = null)
|
||||
{
|
||||
$this->oDriver = $oDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Account $oAccount
|
||||
* @param string $sQuery
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Process(\RainLoop\Account $oAccount, $sQuery)
|
||||
{
|
||||
return $this->oDriver && $this->IsActive() && 0 < \strlen($sQuery) ? $this->oDriver->Process($oAccount, $sQuery) : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\Suggestions\SuggestionsInterface;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\Suggestions;
|
||||
|
||||
interface SuggestionsInterface
|
||||
{
|
||||
/**
|
||||
* @param \RainLoop\Model\Account $oAccount
|
||||
* @param string $sQuery
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Process(\RainLoop\Model\Account $oAccount, $sQuery);
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class TwoFactorAuth extends \RainLoop\Providers\AbstractProvider
|
||||
{
|
||||
/**
|
||||
* @var \RainLoop\Providers\TwoFactorAuth\TwoFactorAuthInterface
|
||||
*/
|
||||
private $oDriver;
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Providers\TwoFactorAuth\TwoFactorAuthInterface|null $oDriver = null
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($oDriver = null)
|
||||
{
|
||||
$this->oDriver = $oDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return $this->oDriver instanceof \RainLoop\Providers\TwoFactorAuth\TwoFactorAuthInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param string $sSecret
|
||||
* @param string $sTitle = ''
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetQRCodeGoogleUrl($sName, $sSecret, $sTitle = '')
|
||||
{
|
||||
$sUrl = sprintf('otpauth://%s/%s?secret=%s&issuer=%s', 'totp', urlencode($sName), $sSecret, urlencode($sTitle));
|
||||
return 'https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl='.\urlencode($sUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function CreateSecret()
|
||||
{
|
||||
$sResult = '';
|
||||
if ($this->IsActive())
|
||||
{
|
||||
$sResult = $this->oDriver->CreateSecret();
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSecret
|
||||
* @param string $sCode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function VerifyCode($sSecret, $sCode)
|
||||
{
|
||||
$bResult = false;
|
||||
if ($this->IsActive())
|
||||
{
|
||||
$bResult = $this->oDriver->VerifyCode($sSecret, $sCode);
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\TwoFactorAuth;
|
||||
|
||||
abstract class AbstractTwoFactorAuth
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Label()
|
||||
{
|
||||
return 'Two Factor Authenticator Code';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSecret
|
||||
* @param string $sCode
|
||||
* @return bool
|
||||
*/
|
||||
public function VerifyCode($sSecret, $sCode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\TwoFactorAuth;
|
||||
|
||||
class GoogleTwoFactorAuth
|
||||
extends \RainLoop\Providers\TwoFactorAuth\AbstractTwoFactorAuth
|
||||
implements \RainLoop\Providers\TwoFactorAuth\TwoFactorAuthInterface
|
||||
{
|
||||
/**
|
||||
* @param string $sSecret
|
||||
* @param string $sCode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function VerifyCode($sSecret, $sCode)
|
||||
{
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/PHPGangsta/GoogleAuthenticator.php';
|
||||
|
||||
$oGoogleAuthenticator = new \PHPGangsta_GoogleAuthenticator();
|
||||
return $oGoogleAuthenticator->verifyCode($sSecret, $sCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function CreateSecret()
|
||||
{
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/PHPGangsta/GoogleAuthenticator.php';
|
||||
|
||||
$oGoogleAuthenticator = new \PHPGangsta_GoogleAuthenticator();
|
||||
return $oGoogleAuthenticator->createSecret();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers\TwoFactorAuth;
|
||||
|
||||
interface TwoFactorAuthInterface
|
||||
{
|
||||
/**
|
||||
* @param string $sSecret
|
||||
* @param string $sCode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function VerifyCode($sSecret, $sCode);
|
||||
}
|
||||
264
rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
Normal file
264
rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Service
|
||||
{
|
||||
/**
|
||||
* @var \MailSo\Base\Http
|
||||
*/
|
||||
private $oHttp;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Actions
|
||||
*/
|
||||
private $oActions;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\ServiceActions
|
||||
*/
|
||||
private $oServiceActions;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
$this->oHttp = \MailSo\Base\Http::SingletonInstance();
|
||||
$this->oActions = \RainLoop\Api::Actions();
|
||||
|
||||
$this->oServiceActions = new \RainLoop\ServiceActions($this->oHttp, $this->oActions);
|
||||
|
||||
if ($this->oActions->Config()->Get('debug', 'enable', false))
|
||||
{
|
||||
\error_reporting(E_ALL);
|
||||
\ini_set('display_errors', 1);
|
||||
}
|
||||
|
||||
$sServer = \trim($this->oActions->Config()->Get('security', 'custom_server_signature', ''));
|
||||
if (0 < \strlen($sServer))
|
||||
{
|
||||
@\header('Server: '.$sServer, true);
|
||||
}
|
||||
|
||||
$sXFrameOptionsHeader = \trim($this->oActions->Config()->Get('security', 'x_frame_options_header', ''));
|
||||
if (0 < \strlen($sXFrameOptionsHeader))
|
||||
{
|
||||
@\header('X-Frame-Options: '.$sXFrameOptionsHeader, true);
|
||||
}
|
||||
|
||||
if ($this->oActions->Config()->Get('labs', 'force_https', false) && !$this->oHttp->IsSecure())
|
||||
{
|
||||
@\header('Location: https://'.$this->oHttp->GetHost(false, false).$this->oHttp->GetUrl(), true);
|
||||
exit();
|
||||
}
|
||||
|
||||
$this->localHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function RunResult()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @staticvar bool $bOne
|
||||
* @return bool
|
||||
*/
|
||||
public static function Handle()
|
||||
{
|
||||
static $bOne = null;
|
||||
if (null === $bOne)
|
||||
{
|
||||
$oService = null;
|
||||
if (\class_exists('MailSo\Version'))
|
||||
{
|
||||
$oService = new self();
|
||||
}
|
||||
|
||||
$bOne = $oService->RunResult();
|
||||
}
|
||||
|
||||
return $bOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Service
|
||||
*/
|
||||
private function localHandle()
|
||||
{
|
||||
if (!\class_exists('MailSo\Version'))
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->oActions->BootStart();
|
||||
|
||||
$sResult = '';
|
||||
$bCached = false;
|
||||
|
||||
$sQuery = $this->oActions->ParseQueryAuthString();
|
||||
|
||||
$this->oActions->Plugins()->RunHook('filter.http-query', array(&$sQuery));
|
||||
$aPaths = \explode('/', $sQuery);
|
||||
$this->oActions->Plugins()->RunHook('filter.http-paths', array(&$aPaths));
|
||||
|
||||
$bAdmin = false;
|
||||
$sAdminPanelHost = $this->oActions->Config()->Get('security', 'admin_panel_host', '');
|
||||
if (empty($sAdminPanelHost))
|
||||
{
|
||||
$bAdmin = !empty($aPaths[0]) && \in_array(\strtolower($aPaths[0]), array('admin', 'cp'));
|
||||
}
|
||||
else if (empty($aPaths[0]) &&
|
||||
\MailSo\Base\Utils::StrToLowerIfAscii($sAdminPanelHost) === \MailSo\Base\Utils::StrToLowerIfAscii($this->oHttp->GetHost()))
|
||||
{
|
||||
$bAdmin = true;
|
||||
}
|
||||
|
||||
if ($this->oHttp->IsPost())
|
||||
{
|
||||
$this->oHttp->ServerNoCache();
|
||||
}
|
||||
|
||||
if ($bAdmin && !$this->oActions->Config()->Get('security', 'allow_admin_panel', true))
|
||||
{
|
||||
echo $this->oActions->ErrorTemplates('Access Denied.',
|
||||
'Access to the RainLoop Webmail Admin Panel is not allowed!', true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$bIndex = true;
|
||||
if (0 < \count($aPaths) && !empty($aPaths[0]) && !$bAdmin && 'index' !== $aPaths[0])
|
||||
{
|
||||
$bIndex = false;
|
||||
$sMethodName = 'Service'.$aPaths[0];
|
||||
if (\method_exists($this->oServiceActions, $sMethodName) &&
|
||||
\is_callable(array($this->oServiceActions, $sMethodName)))
|
||||
{
|
||||
$this->oServiceActions->SetQuery($sQuery)->SetPaths($aPaths);
|
||||
$sResult = \call_user_func(array($this->oServiceActions, $sMethodName));
|
||||
}
|
||||
else if (!$this->oActions->Plugins()->RunAdditionalPart($aPaths[0], $aPaths))
|
||||
{
|
||||
$bIndex = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bIndex)
|
||||
{
|
||||
@header('Content-Type: text/html; charset=utf-8');
|
||||
$this->oHttp->ServerNoCache();
|
||||
|
||||
$aTemplateParameters = $this->indexTemplateParameters($bAdmin);
|
||||
|
||||
$sCacheFileName = '';
|
||||
if ($this->oActions->Config()->Get('labs', 'cache_system_data', true))
|
||||
{
|
||||
$sCacheFileName = 'TMPL:'.$aTemplateParameters['{{BaseHash}}'];
|
||||
$sResult = $this->oActions->Cacher()->Get($sCacheFileName);
|
||||
}
|
||||
|
||||
if (0 === \strlen($sResult))
|
||||
{
|
||||
// $aTemplateParameters['{{BaseTemplates}}'] = $this->oServiceActions->compileTemplates($bAdmin, false);
|
||||
$sResult = \strtr(\file_get_contents(APP_VERSION_ROOT_PATH.'app/templates/Index.html'), $aTemplateParameters);
|
||||
|
||||
$sResult = \RainLoop\Utils::ClearHtmlOutput($sResult);
|
||||
if (0 < \strlen($sCacheFileName))
|
||||
{
|
||||
$this->oActions->Cacher()->Set($sCacheFileName, $sResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$bCached = true;
|
||||
}
|
||||
|
||||
$sResult .= '<!--';
|
||||
$sResult .= ' [version:'.APP_VERSION;
|
||||
$sResult .= '][time:'.\substr(\microtime(true) - APP_START, 0, 6);
|
||||
$sResult .= '][cached:'.($bCached ? 'true' : 'false');
|
||||
$sResult .= '][hash:'.$aTemplateParameters['{{BaseHash}}'];
|
||||
$sResult .= '][session:'.\md5(\RainLoop\Utils::GetShortToken());
|
||||
$sResult .= '] -->';
|
||||
}
|
||||
|
||||
// Output result
|
||||
echo $sResult;
|
||||
unset($sResult);
|
||||
|
||||
$this->oActions->BootEnd();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bAdmin
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function indexTemplateParameters($bAdmin)
|
||||
{
|
||||
$sLanguage = 'en';
|
||||
$sTheme = 'Default';
|
||||
|
||||
if (!$bAdmin)
|
||||
{
|
||||
list($sLanguage, $sTheme) = $this->oActions->GetLanguageAndTheme();
|
||||
}
|
||||
|
||||
$sLanguage = $this->oActions->ValidateLanguage($sLanguage);
|
||||
$sTheme = $this->oActions->ValidateTheme($sTheme);
|
||||
|
||||
$bAppJsDebug = !!$this->oActions->Config()->Get('labs', 'use_app_debug_js', false);
|
||||
$bAppCssDebug = !!$this->oActions->Config()->Get('labs', 'use_app_debug_css', false);
|
||||
|
||||
$sStaticPrefix = APP_WEB_STATIC_PATH;
|
||||
|
||||
$aData = array(
|
||||
'Language' => $sLanguage,
|
||||
'Theme' => $sTheme,
|
||||
'FaviconIcoLink' => $sStaticPrefix.'favicon.ico',
|
||||
'FaviconPngLink' => $sStaticPrefix.'favicon.png',
|
||||
'AppleTouchLink' => $sStaticPrefix.'apple-touch-icon.png',
|
||||
'AppCssLink' => $sStaticPrefix.'css/app'.($bAppCssDebug ? '' : '.min').'.css',
|
||||
'BootJsLink' => $sStaticPrefix.'js/min/boot.js',
|
||||
'ComponentsJsLink' => $sStaticPrefix.'js/'.($bAppJsDebug ? '' : 'min/').'components.js',
|
||||
'LibJsLink' => $sStaticPrefix.'js/min/libs.js',
|
||||
'EditorJsLink' => $sStaticPrefix.'ckeditor/ckeditor.js',
|
||||
'OpenPgpJsLink' => $sStaticPrefix.'js/min/openpgp.min.js',
|
||||
'AppJsCommonLink' => $sStaticPrefix.'js/'.($bAppJsDebug ? '' : 'min/').'common.js',
|
||||
'AppJsLink' => $sStaticPrefix.'js/'.($bAppJsDebug ? '' : 'min/').($bAdmin ? 'admin' : 'app').'.js'
|
||||
);
|
||||
|
||||
$aTemplateParameters = array(
|
||||
'{{BaseAppDataScriptLink}}' => ($bAdmin ? './?/AdminAppData/' : './?/AppData/'),
|
||||
'{{BaseAppFaviconIcoFile}}' => $aData['FaviconIcoLink'],
|
||||
'{{BaseAppFaviconPngFile}}' => $aData['FaviconPngLink'],
|
||||
'{{BaseAppAppleTouchFile}}' => $aData['AppleTouchLink'],
|
||||
'{{BaseAppMainCssLink}}' => $aData['AppCssLink'],
|
||||
'{{BaseAppBootScriptLink}}' => $aData['BootJsLink'],
|
||||
'{{BaseAppComponentsScriptLink}}' => $aData['ComponentsJsLink'],
|
||||
'{{BaseAppLibsScriptLink}}' => $aData['LibJsLink'],
|
||||
'{{BaseAppEditorScriptLink}}' => $aData['EditorJsLink'],
|
||||
'{{BaseAppOpenPgpScriptLink}}' => $aData['OpenPgpJsLink'],
|
||||
'{{BaseAppMainCommonScriptLink}}' => $aData['AppJsCommonLink'],
|
||||
'{{BaseAppMainScriptLink}}' => $aData['AppJsLink'],
|
||||
'{{BaseDir}}' => \in_array($aData['Language'], array('ar', 'he', 'ur')) ? 'rtl' : 'ltr'
|
||||
);
|
||||
|
||||
$aTemplateParameters['{{BaseHash}}'] = \md5(
|
||||
\implode('~', array(
|
||||
\md5($this->oActions->Config()->Get('cache', 'index', '')),
|
||||
$this->oActions->Plugins()->Hash(),
|
||||
APP_WEB_PATH, APP_VERSION
|
||||
)).
|
||||
\implode('~', $aTemplateParameters)
|
||||
);
|
||||
|
||||
return $aTemplateParameters;
|
||||
}
|
||||
}
|
||||
1202
rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
Normal file
1202
rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
Normal file
File diff suppressed because it is too large
Load diff
64
rainloop/v/0.0.0/app/libraries/RainLoop/Settings.php
Normal file
64
rainloop/v/0.0.0/app/libraries/RainLoop/Settings.php
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Settings
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $aData;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->aData = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aData
|
||||
*
|
||||
* @return \RainLoop\Settings
|
||||
*/
|
||||
public function InitData($aData)
|
||||
{
|
||||
if (\is_array($aData))
|
||||
{
|
||||
$this->aData = $aData;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function DataAsArray()
|
||||
{
|
||||
return $this->aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param mixed $mDefValue = null
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetConf($sName, $mDefValue = null)
|
||||
{
|
||||
return isset($this->aData[$sName]) ? $this->aData[$sName] : $mDefValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
* @param mixed $mValue
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function SetConf($sName, $mValue)
|
||||
{
|
||||
$this->aData[$sName] = $mValue;
|
||||
}
|
||||
}
|
||||
877
rainloop/v/0.0.0/app/libraries/RainLoop/Social.php
Normal file
877
rainloop/v/0.0.0/app/libraries/RainLoop/Social.php
Normal file
|
|
@ -0,0 +1,877 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Social
|
||||
{
|
||||
/**
|
||||
* @var \MailSo\Base\Http
|
||||
*/
|
||||
private $oHttp;
|
||||
|
||||
/**
|
||||
* @var \RainLoop\Actions
|
||||
*/
|
||||
private $oActions;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param \MailSo\Base\Http $oHttp
|
||||
* @param \RainLoop\Actions $oActions
|
||||
*/
|
||||
public function __construct($oHttp, $oActions)
|
||||
{
|
||||
$this->oHttp = $oHttp;
|
||||
$this->oActions = $oActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $oItem
|
||||
* @param array $aPics
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
private function convertGoogleJsonContactToResponseContact($oItem, &$aPics)
|
||||
{
|
||||
$mResult = null;
|
||||
if (!empty($oItem['gd$email'][0]['address']))
|
||||
{
|
||||
$mEmail = \MailSo\Base\Utils::IdnToAscii($oItem['gd$email'][0]['address'], true);
|
||||
if (\is_array($oItem['gd$email']) && 1 < \count($oItem['gd$email']))
|
||||
{
|
||||
$mEmail = array();
|
||||
foreach ($oItem['gd$email'] as $oEmail)
|
||||
{
|
||||
if (!empty($oEmail['address']))
|
||||
{
|
||||
$mEmail[] = \MailSo\Base\Utils::IdnToAscii($oEmail['address'], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sImg = '';
|
||||
if (!empty($oItem['link']) && \is_array($oItem['link']))
|
||||
{
|
||||
foreach ($oItem['link'] as $oLink)
|
||||
{
|
||||
if ($oLink && isset($oLink['type'], $oLink['href'], $oLink['rel']) &&
|
||||
'image/*' === $oLink['type'] && '#photo' === \substr($oLink['rel'], -6))
|
||||
{
|
||||
$sImg = $oLink['href'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mResult = array(
|
||||
'email' => $mEmail,
|
||||
'name' => !empty($oItem['title']['$t']) ? $oItem['title']['$t'] : ''
|
||||
);
|
||||
|
||||
if (0 < \strlen($sImg))
|
||||
{
|
||||
$sHash = \RainLoop\Utils::EncodeKeyValues(array(
|
||||
'url' => $sImg,
|
||||
'type' => 'google_access_token'
|
||||
));
|
||||
|
||||
$mData = array();
|
||||
if (isset($aPics[$sHash]))
|
||||
{
|
||||
$mData = $aPics[$sHash];
|
||||
if (!\is_array($mData))
|
||||
{
|
||||
$mData = array($mData);
|
||||
}
|
||||
}
|
||||
|
||||
if (\is_array($mEmail))
|
||||
{
|
||||
$mData = \array_merge($mData, $mEmail);
|
||||
$mData = \array_unique($mData);
|
||||
}
|
||||
else if (0 < \strlen($mEmail))
|
||||
{
|
||||
$mData[] = $mEmail;
|
||||
}
|
||||
|
||||
if (\is_array($mData))
|
||||
{
|
||||
if (1 === \count($mData) && !empty($mData[0]))
|
||||
{
|
||||
$aPics[$sHash] = $mData[0];
|
||||
}
|
||||
else if (1 < \count($mData))
|
||||
{
|
||||
$aPics[$sHash] = $mData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function GoogleUserContacts($oAccount)
|
||||
{
|
||||
$mResult = false;
|
||||
$oGoogle = $this->GoogleConnector();
|
||||
$aPics = array();
|
||||
|
||||
if ($oAccount && $oGoogle)
|
||||
{
|
||||
$sAccessToken = $this->GoogleAccessToken($oAccount, $oGoogle);
|
||||
if (!empty($sAccessToken))
|
||||
{
|
||||
$oGoogle->setAccessToken($sAccessToken);
|
||||
|
||||
$aResponse = $oGoogle->fetch('https://www.google.com/m8/feeds/contacts/default/full', array(
|
||||
'alt' => 'json'
|
||||
));
|
||||
|
||||
if (!empty($aResponse['result']['feed']['entry']) && \is_array($aResponse['result']['feed']['entry']))
|
||||
{
|
||||
$mResult = array();
|
||||
foreach ($aResponse['result']['feed']['entry'] as $oItem)
|
||||
{
|
||||
$aItem = $this->convertGoogleJsonContactToResponseContact($oItem, $aPics);
|
||||
if ($aItem)
|
||||
{
|
||||
if (\is_array($aItem['email']))
|
||||
{
|
||||
$aNewItem = $aItem;
|
||||
unset($aNewItem['email']);
|
||||
|
||||
foreach ($aItem['email'] as $sEmail)
|
||||
{
|
||||
$aNewItem['email'] = $sEmail;
|
||||
$mResult[] = $aNewItem;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$mResult[] = $aItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->oActions->Logger()->Write('Empty Google Access Token', \MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return false !== $mResult ? array(
|
||||
'List' => $mResult,
|
||||
'Pics' => $aPics
|
||||
) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function GoogleDisconnect($oAccount)
|
||||
{
|
||||
$oGoogle = $this->GoogleConnector();
|
||||
if ($oAccount && $oGoogle)
|
||||
{
|
||||
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
|
||||
$sEncodedeData = $oSettings->GetConf('GoogleAccessToken', '');
|
||||
|
||||
if (!empty($sEncodedeData))
|
||||
{
|
||||
$aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData);
|
||||
if (\is_array($aData) && isset($aData['access_token'], $aData['id']))
|
||||
{
|
||||
$this->oActions->StorageProvider()->Clear(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->GoogleUserLoginStorageKey($oGoogle, $aData['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$oSettings->SetConf('GoogleAccessToken', '');
|
||||
$oSettings->SetConf('GoogleSocialName', '');
|
||||
return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function FacebookDisconnect($oAccount)
|
||||
{
|
||||
$oFacebook = $this->FacebookConnector($oAccount ? $oAccount : null);
|
||||
if ($oAccount && $oFacebook)
|
||||
{
|
||||
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
|
||||
|
||||
$sEncodedeData = $oSettings->GetConf('FacebookAccessToken', '');
|
||||
|
||||
if (!empty($sEncodedeData))
|
||||
{
|
||||
$aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData);
|
||||
if (is_array($aData) && isset($aData['id']))
|
||||
{
|
||||
$this->oActions->StorageProvider()->Clear(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->FacebookUserLoginStorageKey($oFacebook, $aData['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$oSettings->SetConf('FacebookAccessToken', '');
|
||||
$oSettings->SetConf('FacebookSocialName', '');
|
||||
|
||||
return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function TwitterDisconnect($oAccount)
|
||||
{
|
||||
$oTwitter = $this->TwitterConnector();
|
||||
if ($oAccount && $oTwitter)
|
||||
{
|
||||
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
|
||||
$sEncodedeData = $oSettings->GetConf('TwitterAccessToken', '');
|
||||
|
||||
if (!empty($sEncodedeData))
|
||||
{
|
||||
$aData = \RainLoop\Utils::DecodeKeyValues($sEncodedeData);
|
||||
if (is_array($aData) && isset($aData['user_id']))
|
||||
{
|
||||
$this->oActions->StorageProvider()->Clear(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->TwitterUserLoginStorageKey($oTwitter, $aData['user_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$oSettings->SetConf('TwitterAccessToken', '');
|
||||
$oSettings->SetConf('TwitterSocialName', '');
|
||||
return $this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GooglePopupService()
|
||||
{
|
||||
$sResult = '';
|
||||
$sLoginUrl = '';
|
||||
|
||||
$bLogin = false;
|
||||
$iErrorCode = \RainLoop\Notifications::UnknownError;
|
||||
|
||||
try
|
||||
{
|
||||
$oGoogle = $this->GoogleConnector();
|
||||
if ($this->oHttp->HasQuery('error'))
|
||||
{
|
||||
$iErrorCode = ('access_denied' === $this->oHttp->GetQuery('error')) ?
|
||||
\RainLoop\Notifications::SocialGoogleLoginAccessDisable : \RainLoop\Notifications::UnknownError;
|
||||
}
|
||||
else if ($oGoogle)
|
||||
{
|
||||
$oAccount = $this->oActions->GetAccount();
|
||||
$bLogin = !$oAccount;
|
||||
|
||||
$sCheckToken = '';
|
||||
$sCheckAuth = '';
|
||||
$sState = $this->oHttp->GetQuery('state');
|
||||
if (!empty($sState))
|
||||
{
|
||||
$aParts = explode('|', $sState, 2);
|
||||
$sCheckToken = !empty($aParts[0]) ? $aParts[0] : '';
|
||||
$sCheckAuth = !empty($aParts[1]) ? $aParts[1] : '';
|
||||
}
|
||||
|
||||
$sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialGoogle';
|
||||
if (!$this->oHttp->HasQuery('code'))
|
||||
{
|
||||
// https://www.google.com/m8/feeds/
|
||||
$aParams = array(
|
||||
'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
|
||||
'state' => \RainLoop\Utils::GetConnectionToken().'|'.$this->oActions->GetSpecAuthToken(),
|
||||
// 'access_type' => 'offline',
|
||||
// 'approval_prompt' => 'force',
|
||||
'response_type' => 'code'
|
||||
);
|
||||
|
||||
$sLoginUrl = $oGoogle->getAuthenticationUrl('https://accounts.google.com/o/oauth2/auth', $sRedirectUrl, $aParams);
|
||||
}
|
||||
else if (!empty($sState) && $sCheckToken === \RainLoop\Utils::GetConnectionToken())
|
||||
{
|
||||
if (!empty($sCheckAuth))
|
||||
{
|
||||
$this->oActions->SetSpecAuthToken($sCheckAuth);
|
||||
$oAccount = $this->oActions->GetAccount();
|
||||
$bLogin = !$oAccount;
|
||||
}
|
||||
|
||||
$aParams = array('code' => $this->oHttp->GetQuery('code'), 'redirect_uri' => $sRedirectUrl);
|
||||
$aAuthorizationResponse = $oGoogle->getAccessToken('https://accounts.google.com/o/oauth2/token', 'authorization_code', $aParams);
|
||||
|
||||
if (!empty($aAuthorizationResponse['result']['access_token']))
|
||||
{
|
||||
$oGoogle->setAccessToken($aAuthorizationResponse['result']['access_token']);
|
||||
$aUserinfoResponse = $oGoogle->fetch('https://www.googleapis.com/oauth2/v2/userinfo');
|
||||
|
||||
if (!empty($aUserinfoResponse['result']['id']))
|
||||
{
|
||||
if ($bLogin)
|
||||
{
|
||||
$sUserData = $this->oActions->StorageProvider()->Get(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->GoogleUserLoginStorageKey($oGoogle, $aUserinfoResponse['result']['id'])
|
||||
);
|
||||
|
||||
$aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
|
||||
|
||||
if ($aUserData && \is_array($aUserData) &&
|
||||
!empty($aUserData['Email']) && isset($aUserData['Password']))
|
||||
{
|
||||
$oAccount = $this->oActions->LoginProcess($aUserData['Email'], $aUserData['Password']);
|
||||
if ($oAccount instanceof \RainLoop\Model\Account)
|
||||
{
|
||||
$this->oActions->AuthToken($oAccount);
|
||||
|
||||
$iErrorCode = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$iErrorCode = \RainLoop\Notifications::SocialGoogleLoginAccessDisable;
|
||||
}
|
||||
}
|
||||
|
||||
if ($oAccount)
|
||||
{
|
||||
$aUserData = array(
|
||||
'Email' => $oAccount->Email(),
|
||||
'Password' => $oAccount->Password()
|
||||
);
|
||||
|
||||
$sSocialName = !empty($aUserinfoResponse['result']['name']) ? $aUserinfoResponse['result']['name'] : '';
|
||||
$sSocialName .= !empty($aUserinfoResponse['result']['email']) ? ' ('.$aUserinfoResponse['result']['email'].')' : '';
|
||||
$sSocialName = \trim($sSocialName);
|
||||
|
||||
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
|
||||
$oSettings->SetConf('GoogleSocialName', $sSocialName);
|
||||
$this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
|
||||
|
||||
$this->oActions->StorageProvider()->Put(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->GoogleUserLoginStorageKey($oGoogle, $aUserinfoResponse['result']['id']),
|
||||
\RainLoop\Utils::EncodeKeyValues($aUserData));
|
||||
|
||||
$iErrorCode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
|
||||
if ($sLoginUrl)
|
||||
{
|
||||
$this->oActions->Location($sLoginUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
@\header('Content-Type: text/html; charset=utf-8');
|
||||
$sCallBackType = $bLogin ? '_login' : '';
|
||||
$sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_google'.$sCallBackType.'_service';
|
||||
$sResult = '<script data-cfasync="false">opener && opener.'.$sConnectionFunc.' && opener.'.
|
||||
$sConnectionFunc.'('.$iErrorCode.'); self && self.close && self.close();</script>';
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function FacebookPopupService()
|
||||
{
|
||||
$sResult = '';
|
||||
$sLoginUrl = '';
|
||||
$sSocialName = '';
|
||||
|
||||
$mData = false;
|
||||
$sUserData = '';
|
||||
$aUserData = false;
|
||||
|
||||
$bLogin = false;
|
||||
$iErrorCode = \RainLoop\Notifications::UnknownError;
|
||||
|
||||
if (0 === \strlen($this->oActions->GetSpecAuthToken()) && $this->oHttp->HasQuery('rlah'))
|
||||
{
|
||||
$this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
|
||||
}
|
||||
|
||||
$oAccount = $this->oActions->GetAccount();
|
||||
|
||||
$oFacebook = $this->FacebookConnector($oAccount);
|
||||
if ($oFacebook)
|
||||
{
|
||||
try
|
||||
{
|
||||
$oSession = $oFacebook->getSessionFromRedirect();
|
||||
if (!$oSession && !$this->oHttp->HasQuery('state'))
|
||||
{
|
||||
$sLoginUrl = $oFacebook->getLoginUrl().'&display=popup';
|
||||
}
|
||||
else if ($oSession)
|
||||
{
|
||||
$oRequest = new \Facebook\FacebookRequest($oSession, 'GET', '/me');
|
||||
$oResponse = $oRequest->execute();
|
||||
$oGraphObject = $oResponse->getGraphObject();
|
||||
|
||||
$mData = $oGraphObject->getProperty('id');
|
||||
$sSocialName = $oGraphObject->getProperty('name');
|
||||
|
||||
if ($oAccount)
|
||||
{
|
||||
if ($mData && 0 < \strlen($mData))
|
||||
{
|
||||
$aUserData = array(
|
||||
'Email' => $oAccount->Email(),
|
||||
'Password' => $oAccount->Password()
|
||||
);
|
||||
|
||||
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
|
||||
$oSettings->SetConf('FacebookSocialName', $sSocialName);
|
||||
$oSettings->SetConf('FacebookAccessToken', \RainLoop\Utils::EncodeKeyValues(array('id' => $mData)));
|
||||
|
||||
|
||||
$this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
|
||||
|
||||
$this->oActions->StorageProvider()->Put(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->FacebookUserLoginStorageKey($oFacebook, $mData),
|
||||
\RainLoop\Utils::EncodeKeyValues($aUserData));
|
||||
|
||||
$iErrorCode = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$bLogin = true;
|
||||
|
||||
if ($mData && 0 < \strlen($mData))
|
||||
{
|
||||
$sUserData = $this->oActions->StorageProvider()->Get(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->FacebookUserLoginStorageKey($oFacebook, $mData));
|
||||
|
||||
if ($sUserData)
|
||||
{
|
||||
$aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
|
||||
}
|
||||
}
|
||||
|
||||
if ($aUserData && \is_array($aUserData) &&
|
||||
!empty($aUserData['Email']) && isset($aUserData['Password']))
|
||||
{
|
||||
$oAccount = $this->oActions->LoginProcess($aUserData['Email'], $aUserData['Password']);
|
||||
if ($oAccount instanceof \RainLoop\Model\Account)
|
||||
{
|
||||
$this->oActions->AuthToken($oAccount);
|
||||
|
||||
$iErrorCode = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$iErrorCode = \RainLoop\Notifications::SocialFacebookLoginAccessDisable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if ($sLoginUrl)
|
||||
{
|
||||
$this->oActions->Location($sLoginUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->oHttp->ServerNoCache();
|
||||
|
||||
@\header('Content-Type: text/html; charset=utf-8');
|
||||
|
||||
$sCallBackType = $bLogin ? '_login' : '';
|
||||
$sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_facebook'.$sCallBackType.'_service';
|
||||
$sResult = '<script data-cfasync="false">opener && opener.'.$sConnectionFunc.' && opener.'.
|
||||
$sConnectionFunc.'('.$iErrorCode.'); self && self.close && self.close();</script>';
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function TwitterPopupService()
|
||||
{
|
||||
$sResult = '';
|
||||
$sLoginUrl = '';
|
||||
|
||||
$sSocialName = '';
|
||||
|
||||
$bLogin = false;
|
||||
$iErrorCode = \RainLoop\Notifications::UnknownError;
|
||||
|
||||
$sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialTwitter';
|
||||
if (0 < strlen($this->oActions->GetSpecAuthToken()))
|
||||
{
|
||||
$sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
|
||||
}
|
||||
else if ($this->oHttp->HasQuery('rlah'))
|
||||
{
|
||||
$this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
|
||||
$sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$oTwitter = $this->TwitterConnector();
|
||||
if ($oTwitter)
|
||||
{
|
||||
$sSessionKey = \implode('_', array('twitter',
|
||||
\md5($oTwitter->config['consumer_secret']), \md5(\RainLoop\Utils::GetConnectionToken()), 'AuthSessionData'));
|
||||
|
||||
$oAccount = $this->oActions->GetAccount();
|
||||
if ($oAccount)
|
||||
{
|
||||
if (isset($_REQUEST['oauth_verifier']))
|
||||
{
|
||||
$sAuth = $this->oActions->Cacher()->Get($sSessionKey);
|
||||
$oAuth = $sAuth ? \json_decode($sAuth, true) : null;
|
||||
|
||||
if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret']))
|
||||
{
|
||||
$oTwitter->config['user_token'] = $oAuth['oauth_token'];
|
||||
$oTwitter->config['user_secret'] = $oAuth['oauth_token_secret'];
|
||||
|
||||
$iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array(
|
||||
'oauth_callback' => $sRedirectUrl,
|
||||
'oauth_verifier' => $_REQUEST['oauth_verifier']
|
||||
));
|
||||
|
||||
if (200 === $iCode && isset($oTwitter->response['response']))
|
||||
{
|
||||
$this->oActions->Logger()->WriteDump($oTwitter->response['response']);
|
||||
$aAccessToken = $oTwitter->extract_params($oTwitter->response['response']);
|
||||
$this->oActions->Logger()->WriteDump($aAccessToken);
|
||||
if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id']))
|
||||
{
|
||||
$oTwitter->config['user_token'] = $aAccessToken['oauth_token'];
|
||||
$oTwitter->config['user_secret'] = $aAccessToken['oauth_token_secret'];
|
||||
|
||||
$sSocialName = !empty($aAccessToken['screen_name']) ? '@'.$aAccessToken['screen_name'] : $aAccessToken['user_id'];
|
||||
$sSocialName = \trim($sSocialName);
|
||||
|
||||
$aUserData = array(
|
||||
'Email' => $oAccount->Email(),
|
||||
'Password' => $oAccount->Password()
|
||||
);
|
||||
|
||||
$oSettings = $this->oActions->SettingsProvider()->Load($oAccount);
|
||||
$oSettings->SetConf('TwitterAccessToken', \RainLoop\Utils::EncodeKeyValues($aAccessToken));
|
||||
$oSettings->SetConf('TwitterSocialName', $sSocialName);
|
||||
$this->oActions->SettingsProvider()->Save($oAccount, $oSettings);
|
||||
|
||||
$this->oActions->StorageProvider()->Put(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['user_id']),
|
||||
\RainLoop\Utils::EncodeKeyValues($aUserData));
|
||||
|
||||
$iErrorCode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aParams = array(
|
||||
'oauth_callback' => $sRedirectUrl,
|
||||
'x_auth_access_type' => 'read'
|
||||
);
|
||||
|
||||
$iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams);
|
||||
if (200 === $iCode && isset($oTwitter->response['response']))
|
||||
{
|
||||
$oAuth = $oTwitter->extract_params($oTwitter->response['response']);
|
||||
if (!empty($oAuth['oauth_token']))
|
||||
{
|
||||
$this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth));
|
||||
$sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$bLogin = true;
|
||||
|
||||
if (isset($_REQUEST['oauth_verifier']))
|
||||
{
|
||||
$sAuth = $this->oActions->Cacher()->Get($sSessionKey);
|
||||
$oAuth = $sAuth ? \json_decode($sAuth, true) : null;
|
||||
if ($oAuth && !empty($oAuth['oauth_token']) && !empty($oAuth['oauth_token_secret']))
|
||||
{
|
||||
$oTwitter->config['user_token'] = $oAuth['oauth_token'];
|
||||
$oTwitter->config['user_secret'] = $oAuth['oauth_token_secret'];
|
||||
|
||||
$iCode = $oTwitter->request('POST', $oTwitter->url('oauth/access_token', ''), array(
|
||||
'oauth_callback' => $sRedirectUrl,
|
||||
'oauth_verifier' => $_REQUEST['oauth_verifier']
|
||||
));
|
||||
|
||||
if (200 === $iCode && isset($oTwitter->response['response']))
|
||||
{
|
||||
$aAccessToken = $oTwitter->extract_params($oTwitter->response['response']);
|
||||
if ($aAccessToken && isset($aAccessToken['oauth_token']) && !empty($aAccessToken['user_id']))
|
||||
{
|
||||
$sUserData = $this->oActions->StorageProvider()->Get(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
$this->TwitterUserLoginStorageKey($oTwitter, $aAccessToken['user_id'])
|
||||
);
|
||||
|
||||
$aUserData = \RainLoop\Utils::DecodeKeyValues($sUserData);
|
||||
|
||||
if ($aUserData && \is_array($aUserData) &&
|
||||
!empty($aUserData['Email']) &&
|
||||
isset($aUserData['Password']))
|
||||
{
|
||||
$oAccount = $this->oActions->LoginProcess($aUserData['Email'], $aUserData['Password']);
|
||||
if ($oAccount instanceof \RainLoop\Model\Account)
|
||||
{
|
||||
$this->oActions->AuthToken($oAccount);
|
||||
|
||||
$iErrorCode = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$iErrorCode = \RainLoop\Notifications::SocialTwitterLoginAccessDisable;
|
||||
}
|
||||
|
||||
$this->oActions->Cacher()->Delete($sSessionKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aParams = array(
|
||||
'oauth_callback' => $sRedirectUrl,
|
||||
'x_auth_access_type' => 'read'
|
||||
);
|
||||
|
||||
$iCode = $oTwitter->request('POST', $oTwitter->url('oauth/request_token', ''), $aParams);
|
||||
if (200 === $iCode && isset($oTwitter->response['response']))
|
||||
{
|
||||
$oAuth = $oTwitter->extract_params($oTwitter->response['response']);
|
||||
if (!empty($oAuth['oauth_token']))
|
||||
{
|
||||
$this->oActions->Cacher()->Set($sSessionKey, \json_encode($oAuth));
|
||||
$sLoginUrl = $oTwitter->url('oauth/authenticate', '').'?oauth_token='.$oAuth['oauth_token'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
|
||||
if ($sLoginUrl)
|
||||
{
|
||||
$this->oActions->Location($sLoginUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
@\header('Content-Type: text/html; charset=utf-8');
|
||||
$sCallBackType = $bLogin ? '_login' : '';
|
||||
$sConnectionFunc = 'rl_'.\md5(\RainLoop\Utils::GetConnectionToken()).'_twitter'.$sCallBackType.'_service';
|
||||
$sResult = '<script data-cfasync="false">opener && opener.'.$sConnectionFunc.' && opener.'.
|
||||
$sConnectionFunc.'('.$iErrorCode.'); self && self.close && self.close();</script>';
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OAuth2\Client|null
|
||||
*/
|
||||
public function GoogleConnector()
|
||||
{
|
||||
$oGoogle = false;
|
||||
$oConfig = $this->oActions->Config();
|
||||
if ($oConfig->Get('social', 'google_enable', false) &&
|
||||
'' !== \trim($oConfig->Get('social', 'google_client_id', '')) &&
|
||||
'' !== \trim($oConfig->Get('social', 'google_client_secret', '')))
|
||||
{
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/Client.php';
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/IGrantType.php';
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/AuthorizationCode.php';
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/PHP-OAuth2/GrantType/RefreshToken.php';
|
||||
|
||||
try
|
||||
{
|
||||
$oGoogle = new \OAuth2\Client(
|
||||
\trim($oConfig->Get('social', 'google_client_id', '')),
|
||||
\trim($oConfig->Get('social', 'google_client_secret', '')));
|
||||
|
||||
$sProxy = $this->oActions->Config()->Get('labs', 'curl_proxy', '');
|
||||
if (0 < \strlen($sProxy))
|
||||
{
|
||||
$oGoogle->setCurlOption(CURLOPT_PROXY, $sProxy);
|
||||
|
||||
$sProxyAuth = $this->oActions->Config()->Get('labs', 'curl_proxy_auth', '');
|
||||
if (0 < \strlen($sProxyAuth))
|
||||
{
|
||||
$oGoogle->setCurlOption(CURLOPT_PROXYUSERPWD, $sProxyAuth);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return false === $oGoogle ? null : $oGoogle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \tmhOAuth|null
|
||||
*/
|
||||
public function TwitterConnector()
|
||||
{
|
||||
$oTwitter = false;
|
||||
$oConfig = $this->oActions->Config();
|
||||
if ($oConfig->Get('social', 'twitter_enable', false) &&
|
||||
'' !== \trim($oConfig->Get('social', 'twitter_consumer_key', '')) &&
|
||||
'' !== \trim($oConfig->Get('social', 'twitter_consumer_secret', '')))
|
||||
{
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhOAuth.php';
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/tmhOAuth/tmhUtilities.php';
|
||||
|
||||
$sProxy = $this->oActions->Config()->Get('labs', 'curl_proxy', '');
|
||||
$sProxyAuth = $this->oActions->Config()->Get('labs', 'curl_proxy_auth', '');
|
||||
|
||||
$oTwitter = new \tmhOAuth(array(
|
||||
'consumer_key' => \trim($oConfig->Get('social', 'twitter_consumer_key', '')),
|
||||
'consumer_secret' => \trim($oConfig->Get('social', 'twitter_consumer_secret', '')),
|
||||
'curl_proxy' => 0 < \strlen($sProxy) ? $sProxy : false,
|
||||
'curl_proxyuserpwd' => 0 < \strlen($sProxyAuth) ? $sProxyAuth : false
|
||||
));
|
||||
}
|
||||
|
||||
return false === $oTwitter ? null : $oTwitter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \RainLoop\Model\Account|null $oAccount = null
|
||||
*
|
||||
* @return \RainLoop\Common\RainLoopFacebookRedirectLoginHelper|null
|
||||
*/
|
||||
public function FacebookConnector($oAccount = null)
|
||||
{
|
||||
$oFacebook = false;
|
||||
$oConfig = $this->oActions->Config();
|
||||
$sAppID = \trim($oConfig->Get('social', 'fb_app_id', ''));
|
||||
|
||||
if (\version_compare(PHP_VERSION, '5.4.0', '>=') &&
|
||||
$oConfig->Get('social', 'fb_enable', false) && '' !== $sAppID &&
|
||||
'' !== \trim($oConfig->Get('social', 'fb_app_secret', '')) &&
|
||||
\class_exists('Facebook\FacebookSession')
|
||||
)
|
||||
{
|
||||
\Facebook\FacebookSession::setDefaultApplication($sAppID,
|
||||
\trim($oConfig->Get('social', 'fb_app_secret', '')));
|
||||
|
||||
$sRedirectUrl = $this->oHttp->GetFullUrl().'?SocialFacebook';
|
||||
if (0 < \strlen($this->oActions->GetSpecAuthToken()))
|
||||
{
|
||||
$sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
|
||||
}
|
||||
else if ($this->oHttp->HasQuery('rlah'))
|
||||
{
|
||||
$this->oActions->SetSpecAuthToken($this->oHttp->GetQuery('rlah', ''));
|
||||
$sRedirectUrl .= '&rlah='.$this->oActions->GetSpecAuthToken();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$oAccount = $this->oActions->GetAccount();
|
||||
|
||||
$oFacebook = new \RainLoop\Common\RainLoopFacebookRedirectLoginHelper($sRedirectUrl);
|
||||
$oFacebook->initRainLoopData(array(
|
||||
'rlAppId' => $sAppID,
|
||||
'rlAccount' => $oAccount,
|
||||
'rlUserHash' => \RainLoop\Utils::GetConnectionToken(),
|
||||
'rlStorageProvaider' => $this->oActions->StorageProvider()
|
||||
));
|
||||
}
|
||||
catch (\Exception $oException)
|
||||
{
|
||||
$this->oActions->Logger()->WriteException($oException, \MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
return false === $oFacebook ? null : $oFacebook;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GoogleUserLoginStorageKey($oGoogle, $sGoogleUserId)
|
||||
{
|
||||
return \implode('_', array('google', \md5($oGoogle->getClientId()), $sGoogleUserId, APP_SALT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function FacebookUserLoginStorageKey($oFacebook, $sFacebookUserId)
|
||||
{
|
||||
return \implode('_', array('facebookNew', \md5($oFacebook->GetRLAppId()), $sFacebookUserId, APP_SALT));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function TwitterUserLoginStorageKey($oTwitter, $sTwitterUserId)
|
||||
{
|
||||
return \implode('_', array('twitter', \md5($oTwitter->config['consumer_secret']), $sTwitterUserId, APP_SALT));
|
||||
}
|
||||
}
|
||||
375
rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
Normal file
375
rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Utils
|
||||
{
|
||||
static $Cookies = null;
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sString
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function EncryptString($sString, $sKey)
|
||||
{
|
||||
return \MailSo\Base\Crypt::XxteaEncrypt($sString, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEncriptedString
|
||||
* @param string $sKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function DecryptString($sEncriptedString, $sKey)
|
||||
{
|
||||
return \MailSo\Base\Crypt::XxteaDecrypt($sEncriptedString, $sKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aValues
|
||||
* @param string $sCustomKey = ''
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
static public function EncodeKeyValues(array $aValues, $sCustomKey = '')
|
||||
{
|
||||
return \MailSo\Base\Utils::UrlSafeBase64Encode(
|
||||
\RainLoop\Utils::EncryptString(\serialize($aValues), \md5(APP_SALT.$sCustomKey)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEncodedValues
|
||||
* @param string $sCustomKey = ''
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static public function DecodeKeyValues($sEncodedValues, $sCustomKey = '')
|
||||
{
|
||||
$aResult = \unserialize(
|
||||
\RainLoop\Utils::DecryptString(
|
||||
\MailSo\Base\Utils::UrlSafeBase64Decode($sEncodedValues), \md5(APP_SALT.$sCustomKey)));
|
||||
|
||||
return \is_array($aResult) ? $aResult : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static public function GetConnectionToken()
|
||||
{
|
||||
$sKey = 'rltoken';
|
||||
|
||||
$sToken = \RainLoop\Utils::GetCookie($sKey, null);
|
||||
if (null === $sToken)
|
||||
{
|
||||
$sToken = \md5(\rand(10000, 99999).\microtime(true).APP_SALT);
|
||||
\RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30, '/', null, null, true);
|
||||
}
|
||||
|
||||
return \md5('Connection'.APP_SALT.$sToken.'Token'.APP_SALT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static public function Fingerprint()
|
||||
{
|
||||
return \md5(empty($_SERVER['HTTP_USER_AGENT']) ? 'RainLoopFingerprint' : $_SERVER['HTTP_USER_AGENT']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static public function GetShortToken()
|
||||
{
|
||||
$sKey = 'rlsession';
|
||||
|
||||
$sToken = \RainLoop\Utils::GetCookie($sKey, null);
|
||||
if (null === $sToken)
|
||||
{
|
||||
$sToken = \md5(\rand(10000, 99999).\microtime(true).APP_SALT);
|
||||
\RainLoop\Utils::SetCookie($sKey, $sToken, 0, '/', null, null, true);
|
||||
}
|
||||
|
||||
return \md5('Session'.APP_SALT.$sToken.'Token'.APP_SALT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
static public function UpdateConnectionToken()
|
||||
{
|
||||
$sKey = 'rltoken';
|
||||
|
||||
$sToken = \RainLoop\Utils::GetCookie($sKey, '');
|
||||
if (!empty($sToken))
|
||||
{
|
||||
\RainLoop\Utils::SetCookie($sKey, $sToken, \time() + 60 * 60 * 24 * 30, '/', null, null, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
static public function GetCsrfToken()
|
||||
{
|
||||
return \md5('Csrf'.APP_SALT.self::GetConnectionToken().'Token'.APP_SALT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPath
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function PathMD5($sPath)
|
||||
{
|
||||
$sResult = '';
|
||||
if (@\is_dir($sPath))
|
||||
{
|
||||
$oDirIterator = new \RecursiveDirectoryIterator($sPath);
|
||||
$oIterator = new \RecursiveIteratorIterator($oDirIterator, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
foreach ($oIterator as $oFile)
|
||||
{
|
||||
$sResult = \md5($sResult.($oFile->isFile() ? \md5_file($oFile) : $oFile));
|
||||
}
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFileName
|
||||
* @param array $aResultLang
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function ReadAndAddLang($sFileName, &$aResultLang)
|
||||
{
|
||||
if (\file_exists($sFileName))
|
||||
{
|
||||
$aLang = \RainLoop\Utils::CustomParseIniFile($sFileName, 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
|
||||
* @param \RainLoop\Actions $oAction
|
||||
* @param string $sNameSuffix = ''
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function CompileTemplates($sDirName, $oAction, $sNameSuffix = '')
|
||||
{
|
||||
$sResult = '';
|
||||
if (\file_exists($sDirName))
|
||||
{
|
||||
$aList = \RainLoop\Utils::FolderFiles($sDirName, '.html');
|
||||
|
||||
foreach ($aList as $sName)
|
||||
{
|
||||
$sTemplateName = \substr($sName, 0, -5).$sNameSuffix;
|
||||
$sResult .= '<script id="'.\preg_replace('/[^a-zA-Z0-9]/', '', $sTemplateName).'" type="text/html" data-cfasync="false">'.
|
||||
$oAction->ProcessTemplate($sTemplateName, \file_get_contents($sDirName.'/'.$sName)).'</script>';
|
||||
}
|
||||
|
||||
$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, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFileName
|
||||
* @param bool $bProcessSections = false
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function CustomParseIniFile($sFileName, $bProcessSections = false)
|
||||
{
|
||||
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('parse_ini_file'))
|
||||
{
|
||||
return @\parse_ini_file($sFileName, !!$bProcessSections);
|
||||
}
|
||||
|
||||
$sData = @\file_get_contents($sFileName);
|
||||
return \is_string($sData) ? @\parse_ini_string($sData, !!$bProcessSections) : null;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue