mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-06 07:57:02 +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
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue