Added "[labs] imap_show_login_alert" setting

Small fixes
This commit is contained in:
RainLoop Team 2015-01-08 18:00:03 +04:00
parent f749d77fff
commit 43d1794423
81 changed files with 132 additions and 48 deletions

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,11 @@
<?php
namespace RainLoop\Providers\AddressBook;
interface AddressBookInterface
{
/**
* @return bool
*/
public function IsSupported();
}

View file

@ -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;
}
}

View file

@ -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;
}
}
}
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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);
}

View 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;
}
}

View file

@ -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));
}
}

View file

@ -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();
}

View file

@ -0,0 +1,7 @@
<?php
namespace RainLoop\Providers\Domain;
interface DomainInterface
{
}

View 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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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()
);
}
}

View file

@ -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()
);
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace RainLoop\Providers\Filters\Enumerations;
class ActionType
{
const NONE = 'None';
const MOVE_TO = 'MoveTo';
const DISCARD = 'Discard';
}

View file

@ -0,0 +1,10 @@
<?php
namespace RainLoop\Providers\Filters\Enumerations;
class ConditionField
{
const FROM = 'From';
const RECIPIENT = 'Recipient';
const SUBJECT = 'Subject';
}

View file

@ -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';
}

View file

@ -0,0 +1,9 @@
<?php
namespace RainLoop\Providers\Filters\Enumerations;
class FilterRulesType
{
const ALL = 'All';
const ANY = 'Any';
}

View file

@ -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);
}

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace RainLoop\Providers\Storage\Enumerations;
class StorageType
{
const USER = 1;
const CONFIG = 2;
const NOBODY = 3;
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace RainLoop\Providers\TwoFactorAuth;
interface TwoFactorAuthInterface
{
/**
* @param string $sSecret
* @param string $sCode
*
* @return bool
*/
public function VerifyCode($sSecret, $sCode);
}