mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-29 20:19:22 +03:00
es5 -> es2015 (last stage)
Signature plugin fixes Add view decorator A large number of fixes
This commit is contained in:
parent
e88c193334
commit
17669b7be0
153 changed files with 21193 additions and 21115 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,274 +1,273 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of MailSo.
|
||||
*
|
||||
* (c) 2014 Usenko Timur
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace MailSo\Imap;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Imap
|
||||
*/
|
||||
class FetchResponse
|
||||
{
|
||||
/**
|
||||
* @var \MailSo\Imap\Response
|
||||
*/
|
||||
private $oImapResponse;
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
private $aEnvelopeCache;
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
*/
|
||||
private function __construct($oImapResponse)
|
||||
{
|
||||
$this->oImapResponse = $oImapResponse;
|
||||
$this->aEnvelopeCache = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
* @return \MailSo\Imap\FetchResponse
|
||||
*/
|
||||
public static function NewInstance($oImapResponse)
|
||||
{
|
||||
return new self($oImapResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bForce = false
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function GetEnvelope($bForce = false)
|
||||
{
|
||||
if (null === $this->aEnvelopeCache || $bForce)
|
||||
{
|
||||
$this->aEnvelopeCache = $this->GetFetchValue(Enumerations\FetchType::ENVELOPE);
|
||||
}
|
||||
return $this->aEnvelopeCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iIndex
|
||||
* @param mixed $mNullResult = null
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetFetchEnvelopeValue($iIndex, $mNullResult)
|
||||
{
|
||||
return self::findEnvelopeIndex($this->GetEnvelope(), $iIndex, $mNullResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iIndex
|
||||
* @param string $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1
|
||||
*
|
||||
* @return \MailSo\Mime\EmailCollection|null
|
||||
*/
|
||||
public function GetFetchEnvelopeEmailCollection($iIndex, $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1)
|
||||
{
|
||||
$oResult = null;
|
||||
$aEmails = $this->GetFetchEnvelopeValue($iIndex, null);
|
||||
if (is_array($aEmails) && 0 < count($aEmails))
|
||||
{
|
||||
$oResult = \MailSo\Mime\EmailCollection::NewInstance();
|
||||
foreach ($aEmails as $aEmailItem)
|
||||
{
|
||||
if (is_array($aEmailItem) && 4 === count($aEmailItem))
|
||||
{
|
||||
$sDisplayName = \MailSo\Base\Utils::DecodeHeaderValue(
|
||||
self::findEnvelopeIndex($aEmailItem, 0, ''), $sParentCharset);
|
||||
|
||||
$sRemark = \MailSo\Base\Utils::DecodeHeaderValue(
|
||||
self::findEnvelopeIndex($aEmailItem, 1, ''), $sParentCharset);
|
||||
|
||||
$sLocalPart = self::findEnvelopeIndex($aEmailItem, 2, '');
|
||||
$sDomainPart = self::findEnvelopeIndex($aEmailItem, 3, '');
|
||||
|
||||
if (0 < strlen($sLocalPart) && 0 < strlen($sDomainPart))
|
||||
{
|
||||
$oResult->Add(
|
||||
\MailSo\Mime\Email::NewInstance(
|
||||
$sLocalPart.'@'.$sDomainPart, $sDisplayName, $sRemark)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $oResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRfc822SubMimeIndex = ''
|
||||
*
|
||||
* @return \MailSo\Imap\BodyStructure|null
|
||||
*/
|
||||
public function GetFetchBodyStructure($sRfc822SubMimeIndex = '')
|
||||
{
|
||||
$oBodyStructure = null;
|
||||
$aBodyStructureArray = $this->GetFetchValue(Enumerations\FetchType::BODYSTRUCTURE);
|
||||
|
||||
if (is_array($aBodyStructureArray))
|
||||
{
|
||||
if (0 < strlen($sRfc822SubMimeIndex))
|
||||
{
|
||||
$oBodyStructure = BodyStructure::NewInstanceFromRfc822SubPart($aBodyStructureArray, $sRfc822SubMimeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oBodyStructure = BodyStructure::NewInstance($aBodyStructureArray);
|
||||
}
|
||||
}
|
||||
|
||||
return $oBodyStructure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFetchItemName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetFetchValue($sFetchItemName)
|
||||
{
|
||||
$mReturn = null;
|
||||
$bNextIsValue = false;
|
||||
|
||||
if (Enumerations\FetchType::INDEX === $sFetchItemName)
|
||||
{
|
||||
$mReturn = $this->oImapResponse->ResponseList[1];
|
||||
}
|
||||
else if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3]))
|
||||
{
|
||||
foreach ($this->oImapResponse->ResponseList[3] as $mItem)
|
||||
{
|
||||
if ($bNextIsValue)
|
||||
{
|
||||
$mReturn = $mItem;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($sFetchItemName === $mItem)
|
||||
{
|
||||
$bNextIsValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRfc822SubMimeIndex = ''
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetHeaderFieldsValue($sRfc822SubMimeIndex = '')
|
||||
{
|
||||
$sReturn = '';
|
||||
$bNextIsValue = false;
|
||||
|
||||
$sRfc822SubMimeIndex = 0 < \strlen($sRfc822SubMimeIndex) ? ''.$sRfc822SubMimeIndex.'.' : '';
|
||||
|
||||
if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3]))
|
||||
{
|
||||
foreach ($this->oImapResponse->ResponseList[3] as $mItem)
|
||||
{
|
||||
if ($bNextIsValue)
|
||||
{
|
||||
$sReturn = (string) $mItem;
|
||||
break;
|
||||
}
|
||||
|
||||
if (\is_string($mItem) && (
|
||||
$mItem === 'BODY['.$sRfc822SubMimeIndex.'HEADER]' ||
|
||||
0 === \strpos($mItem, 'BODY['.$sRfc822SubMimeIndex.'HEADER.FIELDS') ||
|
||||
$mItem === 'BODY['.$sRfc822SubMimeIndex.'MIME]'))
|
||||
{
|
||||
$bNextIsValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sReturn;
|
||||
}
|
||||
|
||||
private static function findFetchUidAndSize($aList)
|
||||
{
|
||||
$bUid = false;
|
||||
$bSize = false;
|
||||
if (is_array($aList))
|
||||
{
|
||||
foreach ($aList as $mItem)
|
||||
{
|
||||
if (\MailSo\Imap\Enumerations\FetchType::UID === $mItem)
|
||||
{
|
||||
$bUid = true;
|
||||
}
|
||||
else if (\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE === $mItem)
|
||||
{
|
||||
$bSize = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bUid && $bSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function IsValidFetchImapResponse($oImapResponse)
|
||||
{
|
||||
return (
|
||||
$oImapResponse
|
||||
&& true !== $oImapResponse->IsStatusResponse
|
||||
&& \MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType
|
||||
&& 3 < count($oImapResponse->ResponseList) && 'FETCH' === $oImapResponse->ResponseList[2]
|
||||
&& is_array($oImapResponse->ResponseList[3])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function IsNotEmptyFetchImapResponse($oImapResponse)
|
||||
{
|
||||
return (
|
||||
$oImapResponse
|
||||
&& self::IsValidFetchImapResponse($oImapResponse)
|
||||
&& isset($oImapResponse->ResponseList[3])
|
||||
&& self::findFetchUidAndSize($oImapResponse->ResponseList[3])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aEnvelope
|
||||
* @param int $iIndex
|
||||
* @param mixed $mNullResult = null
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function findEnvelopeIndex($aEnvelope, $iIndex, $mNullResult)
|
||||
{
|
||||
return (isset($aEnvelope[$iIndex]) && 'NIL' !== $aEnvelope[$iIndex] && '' !== $aEnvelope[$iIndex])
|
||||
? $aEnvelope[$iIndex] : $mNullResult;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of MailSo.
|
||||
*
|
||||
* (c) 2014 Usenko Timur
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace MailSo\Imap;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Imap
|
||||
*/
|
||||
class FetchResponse
|
||||
{
|
||||
/**
|
||||
* @var \MailSo\Imap\Response
|
||||
*/
|
||||
private $oImapResponse;
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
private $aEnvelopeCache;
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
*/
|
||||
private function __construct($oImapResponse)
|
||||
{
|
||||
$this->oImapResponse = $oImapResponse;
|
||||
$this->aEnvelopeCache = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
* @return \MailSo\Imap\FetchResponse
|
||||
*/
|
||||
public static function NewInstance($oImapResponse)
|
||||
{
|
||||
return new self($oImapResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bForce = false
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function GetEnvelope($bForce = false)
|
||||
{
|
||||
if (null === $this->aEnvelopeCache || $bForce)
|
||||
{
|
||||
$this->aEnvelopeCache = $this->GetFetchValue(Enumerations\FetchType::ENVELOPE);
|
||||
}
|
||||
return $this->aEnvelopeCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iIndex
|
||||
* @param mixed $mNullResult = null
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetFetchEnvelopeValue($iIndex, $mNullResult)
|
||||
{
|
||||
return self::findEnvelopeIndex($this->GetEnvelope(), $iIndex, $mNullResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iIndex
|
||||
* @param string $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1
|
||||
*
|
||||
* @return \MailSo\Mime\EmailCollection|null
|
||||
*/
|
||||
public function GetFetchEnvelopeEmailCollection($iIndex, $sParentCharset = \MailSo\Base\Enumerations\Charset::ISO_8859_1)
|
||||
{
|
||||
$oResult = null;
|
||||
$aEmails = $this->GetFetchEnvelopeValue($iIndex, null);
|
||||
if (is_array($aEmails) && 0 < count($aEmails))
|
||||
{
|
||||
$oResult = \MailSo\Mime\EmailCollection::NewInstance();
|
||||
foreach ($aEmails as $aEmailItem)
|
||||
{
|
||||
if (is_array($aEmailItem) && 4 === count($aEmailItem))
|
||||
{
|
||||
$sDisplayName = \MailSo\Base\Utils::DecodeHeaderValue(
|
||||
self::findEnvelopeIndex($aEmailItem, 0, ''), $sParentCharset);
|
||||
|
||||
// $sRemark = \MailSo\Base\Utils::DecodeHeaderValue(
|
||||
// self::findEnvelopeIndex($aEmailItem, 1, ''), $sParentCharset);
|
||||
|
||||
$sLocalPart = self::findEnvelopeIndex($aEmailItem, 2, '');
|
||||
$sDomainPart = self::findEnvelopeIndex($aEmailItem, 3, '');
|
||||
|
||||
if (0 < strlen($sLocalPart) && 0 < strlen($sDomainPart))
|
||||
{
|
||||
$oResult->Add(
|
||||
\MailSo\Mime\Email::NewInstance($sLocalPart.'@'.$sDomainPart, $sDisplayName)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $oResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRfc822SubMimeIndex = ''
|
||||
*
|
||||
* @return \MailSo\Imap\BodyStructure|null
|
||||
*/
|
||||
public function GetFetchBodyStructure($sRfc822SubMimeIndex = '')
|
||||
{
|
||||
$oBodyStructure = null;
|
||||
$aBodyStructureArray = $this->GetFetchValue(Enumerations\FetchType::BODYSTRUCTURE);
|
||||
|
||||
if (is_array($aBodyStructureArray))
|
||||
{
|
||||
if (0 < strlen($sRfc822SubMimeIndex))
|
||||
{
|
||||
$oBodyStructure = BodyStructure::NewInstanceFromRfc822SubPart($aBodyStructureArray, $sRfc822SubMimeIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oBodyStructure = BodyStructure::NewInstance($aBodyStructureArray);
|
||||
}
|
||||
}
|
||||
|
||||
return $oBodyStructure;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sFetchItemName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetFetchValue($sFetchItemName)
|
||||
{
|
||||
$mReturn = null;
|
||||
$bNextIsValue = false;
|
||||
|
||||
if (Enumerations\FetchType::INDEX === $sFetchItemName)
|
||||
{
|
||||
$mReturn = $this->oImapResponse->ResponseList[1];
|
||||
}
|
||||
else if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3]))
|
||||
{
|
||||
foreach ($this->oImapResponse->ResponseList[3] as $mItem)
|
||||
{
|
||||
if ($bNextIsValue)
|
||||
{
|
||||
$mReturn = $mItem;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($sFetchItemName === $mItem)
|
||||
{
|
||||
$bNextIsValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRfc822SubMimeIndex = ''
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetHeaderFieldsValue($sRfc822SubMimeIndex = '')
|
||||
{
|
||||
$sReturn = '';
|
||||
$bNextIsValue = false;
|
||||
|
||||
$sRfc822SubMimeIndex = 0 < \strlen($sRfc822SubMimeIndex) ? ''.$sRfc822SubMimeIndex.'.' : '';
|
||||
|
||||
if (isset($this->oImapResponse->ResponseList[3]) && \is_array($this->oImapResponse->ResponseList[3]))
|
||||
{
|
||||
foreach ($this->oImapResponse->ResponseList[3] as $mItem)
|
||||
{
|
||||
if ($bNextIsValue)
|
||||
{
|
||||
$sReturn = (string) $mItem;
|
||||
break;
|
||||
}
|
||||
|
||||
if (\is_string($mItem) && (
|
||||
$mItem === 'BODY['.$sRfc822SubMimeIndex.'HEADER]' ||
|
||||
0 === \strpos($mItem, 'BODY['.$sRfc822SubMimeIndex.'HEADER.FIELDS') ||
|
||||
$mItem === 'BODY['.$sRfc822SubMimeIndex.'MIME]'))
|
||||
{
|
||||
$bNextIsValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sReturn;
|
||||
}
|
||||
|
||||
private static function findFetchUidAndSize($aList)
|
||||
{
|
||||
$bUid = false;
|
||||
$bSize = false;
|
||||
if (is_array($aList))
|
||||
{
|
||||
foreach ($aList as $mItem)
|
||||
{
|
||||
if (\MailSo\Imap\Enumerations\FetchType::UID === $mItem)
|
||||
{
|
||||
$bUid = true;
|
||||
}
|
||||
else if (\MailSo\Imap\Enumerations\FetchType::RFC822_SIZE === $mItem)
|
||||
{
|
||||
$bSize = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $bUid && $bSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function IsValidFetchImapResponse($oImapResponse)
|
||||
{
|
||||
return (
|
||||
$oImapResponse
|
||||
&& true !== $oImapResponse->IsStatusResponse
|
||||
&& \MailSo\Imap\Enumerations\ResponseType::UNTAGGED === $oImapResponse->ResponseType
|
||||
&& 3 < count($oImapResponse->ResponseList) && 'FETCH' === $oImapResponse->ResponseList[2]
|
||||
&& is_array($oImapResponse->ResponseList[3])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \MailSo\Imap\Response $oImapResponse
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function IsNotEmptyFetchImapResponse($oImapResponse)
|
||||
{
|
||||
return (
|
||||
$oImapResponse
|
||||
&& self::IsValidFetchImapResponse($oImapResponse)
|
||||
&& isset($oImapResponse->ResponseList[3])
|
||||
&& self::findFetchUidAndSize($oImapResponse->ResponseList[3])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aEnvelope
|
||||
* @param int $iIndex
|
||||
* @param mixed $mNullResult = null
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function findEnvelopeIndex($aEnvelope, $iIndex, $mNullResult)
|
||||
{
|
||||
return (isset($aEnvelope[$iIndex]) && 'NIL' !== $aEnvelope[$iIndex] && '' !== $aEnvelope[$iIndex])
|
||||
? $aEnvelope[$iIndex] : $mNullResult;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,338 +1,315 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of MailSo.
|
||||
*
|
||||
* (c) 2014 Usenko Timur
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace MailSo\Mime;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Mime
|
||||
*/
|
||||
class Email
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDisplayName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sEmail;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sRemark;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDkimStatus;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDkimValue;
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*
|
||||
* @param string $sEmail
|
||||
* @param string $sDisplayName = ''
|
||||
* @param string $sRemark = ''
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
private function __construct($sEmail, $sDisplayName = '', $sRemark = '')
|
||||
{
|
||||
if (!\MailSo\Base\Validator::NotEmptyString($sEmail, true))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||
}
|
||||
|
||||
$this->sEmail = \MailSo\Base\Utils::IdnToAscii(
|
||||
\MailSo\Base\Utils::Trim($sEmail), true);
|
||||
|
||||
$this->sDisplayName = \MailSo\Base\Utils::Trim($sDisplayName);
|
||||
$this->sRemark = \MailSo\Base\Utils::Trim($sRemark);
|
||||
|
||||
$this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::NONE;
|
||||
$this->sDkimValue = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sDisplayName = ''
|
||||
* @param string $sRemark = ''
|
||||
*
|
||||
* @return \MailSo\Mime\Email
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public static function NewInstance($sEmail, $sDisplayName = '', $sRemark = '')
|
||||
{
|
||||
return new self($sEmail, $sDisplayName, $sRemark);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmailAddress
|
||||
* @return \MailSo\Mime\Email
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public static function Parse($sEmailAddress)
|
||||
{
|
||||
$sEmailAddress = \MailSo\Base\Utils::Trim($sEmailAddress);
|
||||
if (!\MailSo\Base\Validator::NotEmptyString($sEmailAddress, true))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||
}
|
||||
|
||||
$sName = '';
|
||||
$sEmail = '';
|
||||
$sComment = '';
|
||||
|
||||
$bInName = false;
|
||||
$bInAddress = false;
|
||||
$bInComment = false;
|
||||
|
||||
$iStartIndex = 0;
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
|
||||
while ($iCurrentIndex < \strlen($sEmailAddress))
|
||||
{
|
||||
switch ($sEmailAddress{$iCurrentIndex})
|
||||
{
|
||||
// case '\'':
|
||||
case '"':
|
||||
// $sQuoteChar = $sEmailAddress{$iCurrentIndex};
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInName = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
else if ((!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sName = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInName = false;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
if ($iCurrentIndex > 0 && \strlen($sName) === 0)
|
||||
{
|
||||
$sName = \substr($sEmailAddress, 0, $iCurrentIndex);
|
||||
}
|
||||
|
||||
$bInAddress = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if ($bInAddress)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sEmail = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInAddress = false;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInComment = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case ')':
|
||||
if ($bInComment)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sComment = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInComment = false;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
$iCurrentIndex++;
|
||||
break;
|
||||
}
|
||||
|
||||
$iCurrentIndex++;
|
||||
}
|
||||
|
||||
if (\strlen($sEmail) === 0)
|
||||
{
|
||||
$aRegs = array('');
|
||||
if (\preg_match('/[^@\s]+@\S+/i', $sEmailAddress, $aRegs) && isset($aRegs[0]))
|
||||
{
|
||||
$sEmail = $aRegs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sName = $sEmailAddress;
|
||||
}
|
||||
}
|
||||
|
||||
if ((\strlen($sEmail) > 0) && (\strlen($sName) == 0) && (\strlen($sComment) == 0))
|
||||
{
|
||||
$sName = \str_replace($sEmail, '', $sEmailAddress);
|
||||
}
|
||||
|
||||
$sEmail = \trim(\trim($sEmail), '<>');
|
||||
$sEmail = \rtrim(\trim($sEmail), '.');
|
||||
$sEmail = \trim($sEmail);
|
||||
|
||||
$sName = \trim(\trim($sName), '"');
|
||||
$sName = \trim($sName, '\'');
|
||||
$sComment = \trim(\trim($sComment), '()');
|
||||
|
||||
// Remove backslash
|
||||
$sName = \preg_replace('/\\\\(.)/s', '$1', $sName);
|
||||
$sComment = \preg_replace('/\\\\(.)/s', '$1', $sComment);
|
||||
|
||||
return Email::NewInstance($sEmail, $sName, $sComment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetEmail($bIdn = false)
|
||||
{
|
||||
return $bIdn ? \MailSo\Base\Utils::IdnToUtf8($this->sEmail) : $this->sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDisplayName()
|
||||
{
|
||||
return $this->sDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetRemark()
|
||||
{
|
||||
return $this->sRemark;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDkimStatus()
|
||||
{
|
||||
return $this->sDkimStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDkimValue()
|
||||
{
|
||||
return $this->sDkimValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetAccountName()
|
||||
{
|
||||
return \MailSo\Base\Utils::GetAccountNameFromEmail($this->GetEmail(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetDomain($bIdn = false)
|
||||
{
|
||||
return \MailSo\Base\Utils::GetDomainFromEmail($this->GetEmail($bIdn));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDkimStatus
|
||||
* @param string $sDkimValue = ''
|
||||
*/
|
||||
public function SetDkimStatusAndValue($sDkimStatus, $sDkimValue = '')
|
||||
{
|
||||
$this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::normalizeValue($sDkimStatus);
|
||||
$this->sDkimValue = $sDkimValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
* @param bool $bDkim = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ToArray($bIdn = false, $bDkim = true)
|
||||
{
|
||||
return $bDkim ? array($this->sDisplayName, $this->GetEmail($bIdn), $this->sRemark, $this->sDkimStatus, $this->sDkimValue) :
|
||||
array($this->sDisplayName, $this->GetEmail($bIdn), $this->sRemark);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bConvertSpecialsName = false
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ToString($bConvertSpecialsName = false, $bIdn = false)
|
||||
{
|
||||
$sReturn = '';
|
||||
|
||||
$sRemark = \str_replace(')', '\)', $this->sRemark);
|
||||
$sDisplayName = \str_replace('"', '\"', $this->sDisplayName);
|
||||
|
||||
if ($bConvertSpecialsName)
|
||||
{
|
||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
|
||||
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||
$sDisplayName);
|
||||
|
||||
$sRemark = 0 === \strlen($sRemark) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
|
||||
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||
$sRemark);
|
||||
}
|
||||
|
||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : '"'.$sDisplayName.'"';
|
||||
$sRemark = 0 === \strlen($sRemark) ? '' : '('.$sRemark.')';
|
||||
|
||||
if (0 < \strlen($this->sEmail))
|
||||
{
|
||||
$sReturn = $this->GetEmail($bIdn);
|
||||
if (0 < \strlen($sDisplayName.$sRemark))
|
||||
{
|
||||
$sReturn = $sDisplayName.' <'.$sReturn.'> '.$sRemark;
|
||||
}
|
||||
}
|
||||
|
||||
return \trim($sReturn);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of MailSo.
|
||||
*
|
||||
* (c) 2014 Usenko Timur
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace MailSo\Mime;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
* @package Mime
|
||||
*/
|
||||
class Email
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDisplayName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sEmail;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDkimStatus;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDkimValue;
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*
|
||||
* @param string $sEmail
|
||||
* @param string $sDisplayName = ''
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
private function __construct($sEmail, $sDisplayName = '')
|
||||
{
|
||||
if (!\MailSo\Base\Validator::NotEmptyString($sEmail, true))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||
}
|
||||
|
||||
$this->sEmail = \MailSo\Base\Utils::IdnToAscii(
|
||||
\MailSo\Base\Utils::Trim($sEmail), true);
|
||||
|
||||
$this->sDisplayName = \MailSo\Base\Utils::Trim($sDisplayName);
|
||||
|
||||
$this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::NONE;
|
||||
$this->sDkimValue = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sDisplayName = ''
|
||||
*
|
||||
* @return \MailSo\Mime\Email
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public static function NewInstance($sEmail, $sDisplayName = '')
|
||||
{
|
||||
return new self($sEmail, $sDisplayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmailAddress
|
||||
* @return \MailSo\Mime\Email
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public static function Parse($sEmailAddress)
|
||||
{
|
||||
$sEmailAddress = \MailSo\Base\Utils::Trim($sEmailAddress);
|
||||
if (!\MailSo\Base\Validator::NotEmptyString($sEmailAddress, true))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||
}
|
||||
|
||||
$sName = '';
|
||||
$sEmail = '';
|
||||
$sComment = '';
|
||||
|
||||
$bInName = false;
|
||||
$bInAddress = false;
|
||||
$bInComment = false;
|
||||
|
||||
$iStartIndex = 0;
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
|
||||
while ($iCurrentIndex < \strlen($sEmailAddress))
|
||||
{
|
||||
switch ($sEmailAddress{$iCurrentIndex})
|
||||
{
|
||||
// case '\'':
|
||||
case '"':
|
||||
// $sQuoteChar = $sEmailAddress{$iCurrentIndex};
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInName = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
else if ((!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sName = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInName = false;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
if ($iCurrentIndex > 0 && \strlen($sName) === 0)
|
||||
{
|
||||
$sName = \substr($sEmailAddress, 0, $iCurrentIndex);
|
||||
}
|
||||
|
||||
$bInAddress = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if ($bInAddress)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sEmail = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInAddress = false;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInComment = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case ')':
|
||||
if ($bInComment)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sComment = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInComment = false;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
$iCurrentIndex++;
|
||||
break;
|
||||
}
|
||||
|
||||
$iCurrentIndex++;
|
||||
}
|
||||
|
||||
if (\strlen($sEmail) === 0)
|
||||
{
|
||||
$aRegs = array('');
|
||||
if (\preg_match('/[^@\s]+@\S+/i', $sEmailAddress, $aRegs) && isset($aRegs[0]))
|
||||
{
|
||||
$sEmail = $aRegs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sName = $sEmailAddress;
|
||||
}
|
||||
}
|
||||
|
||||
if ((\strlen($sEmail) > 0) && (\strlen($sName) == 0) && (\strlen($sComment) == 0))
|
||||
{
|
||||
$sName = \str_replace($sEmail, '', $sEmailAddress);
|
||||
}
|
||||
|
||||
$sEmail = \trim(\trim($sEmail), '<>');
|
||||
$sEmail = \rtrim(\trim($sEmail), '.');
|
||||
$sEmail = \trim($sEmail);
|
||||
|
||||
$sName = \trim(\trim($sName), '"');
|
||||
$sName = \trim($sName, '\'');
|
||||
$sComment = \trim(\trim($sComment), '()');
|
||||
|
||||
// Remove backslash
|
||||
$sName = \preg_replace('/\\\\(.)/s', '$1', $sName);
|
||||
$sComment = \preg_replace('/\\\\(.)/s', '$1', $sComment);
|
||||
|
||||
return Email::NewInstance($sEmail, $sName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetEmail($bIdn = false)
|
||||
{
|
||||
return $bIdn ? \MailSo\Base\Utils::IdnToUtf8($this->sEmail) : $this->sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDisplayName()
|
||||
{
|
||||
return $this->sDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDkimStatus()
|
||||
{
|
||||
return $this->sDkimStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDkimValue()
|
||||
{
|
||||
return $this->sDkimValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetAccountName()
|
||||
{
|
||||
return \MailSo\Base\Utils::GetAccountNameFromEmail($this->GetEmail(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetDomain($bIdn = false)
|
||||
{
|
||||
return \MailSo\Base\Utils::GetDomainFromEmail($this->GetEmail($bIdn));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDkimStatus
|
||||
* @param string $sDkimValue = ''
|
||||
*/
|
||||
public function SetDkimStatusAndValue($sDkimStatus, $sDkimValue = '')
|
||||
{
|
||||
$this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::normalizeValue($sDkimStatus);
|
||||
$this->sDkimValue = $sDkimValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
* @param bool $bDkim = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ToArray($bIdn = false, $bDkim = true)
|
||||
{
|
||||
return $bDkim ?
|
||||
array($this->sDisplayName, $this->GetEmail($bIdn), $this->sDkimStatus, $this->sDkimValue) :
|
||||
array($this->sDisplayName, $this->GetEmail($bIdn));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bConvertSpecialsName = false
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ToString($bConvertSpecialsName = false, $bIdn = false)
|
||||
{
|
||||
$sReturn = '';
|
||||
|
||||
$sDisplayName = \str_replace('"', '\"', $this->sDisplayName);
|
||||
if ($bConvertSpecialsName)
|
||||
{
|
||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
|
||||
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||
$sDisplayName);
|
||||
}
|
||||
|
||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : '"'.$sDisplayName.'"';
|
||||
if (0 < \strlen($this->sEmail))
|
||||
{
|
||||
$sReturn = $this->GetEmail($bIdn);
|
||||
if (0 < \strlen($sDisplayName))
|
||||
{
|
||||
$sReturn = $sDisplayName.' <'.$sReturn.'>';
|
||||
}
|
||||
}
|
||||
|
||||
return \trim($sReturn);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
339
rainloop/v/0.0.0/app/libraries/MailSo/Mime/EmailDep.php
Normal file
339
rainloop/v/0.0.0/app/libraries/MailSo/Mime/EmailDep.php
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of MailSo.
|
||||
*
|
||||
* (c) 2014 Usenko Timur
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace MailSo\Mime;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @category MailSo
|
||||
* @package Mime
|
||||
*/
|
||||
class EmailDep
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDisplayName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sEmail;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sRemark;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDkimStatus;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $sDkimValue;
|
||||
|
||||
/**
|
||||
* @access private
|
||||
*
|
||||
* @param string $sEmail
|
||||
* @param string $sDisplayName = ''
|
||||
* @param string $sRemark = ''
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
private function __construct($sEmail, $sDisplayName = '', $sRemark = '')
|
||||
{
|
||||
if (!\MailSo\Base\Validator::NotEmptyString($sEmail, true))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||
}
|
||||
|
||||
$this->sEmail = \MailSo\Base\Utils::IdnToAscii(
|
||||
\MailSo\Base\Utils::Trim($sEmail), true);
|
||||
|
||||
$this->sDisplayName = \MailSo\Base\Utils::Trim($sDisplayName);
|
||||
$this->sRemark = \MailSo\Base\Utils::Trim($sRemark);
|
||||
|
||||
$this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::NONE;
|
||||
$this->sDkimValue = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sDisplayName = ''
|
||||
* @param string $sRemark = ''
|
||||
*
|
||||
* @return \MailSo\Mime\Email
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public static function NewInstance($sEmail, $sDisplayName = '', $sRemark = '')
|
||||
{
|
||||
return new self($sEmail, $sDisplayName, $sRemark);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmailAddress
|
||||
* @return \MailSo\Mime\Email
|
||||
*
|
||||
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||
*/
|
||||
public static function Parse($sEmailAddress)
|
||||
{
|
||||
$sEmailAddress = \MailSo\Base\Utils::Trim($sEmailAddress);
|
||||
if (!\MailSo\Base\Validator::NotEmptyString($sEmailAddress, true))
|
||||
{
|
||||
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||
}
|
||||
|
||||
$sName = '';
|
||||
$sEmail = '';
|
||||
$sComment = '';
|
||||
|
||||
$bInName = false;
|
||||
$bInAddress = false;
|
||||
$bInComment = false;
|
||||
|
||||
$iStartIndex = 0;
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
|
||||
while ($iCurrentIndex < \strlen($sEmailAddress))
|
||||
{
|
||||
switch ($sEmailAddress{$iCurrentIndex})
|
||||
{
|
||||
// case '\'':
|
||||
case '"':
|
||||
// $sQuoteChar = $sEmailAddress{$iCurrentIndex};
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInName = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
else if ((!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sName = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInName = false;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
if ($iCurrentIndex > 0 && \strlen($sName) === 0)
|
||||
{
|
||||
$sName = \substr($sEmailAddress, 0, $iCurrentIndex);
|
||||
}
|
||||
|
||||
$bInAddress = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if ($bInAddress)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sEmail = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInAddress = false;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
if ((!$bInName) && (!$bInAddress) && (!$bInComment))
|
||||
{
|
||||
$bInComment = true;
|
||||
$iStartIndex = $iCurrentIndex;
|
||||
}
|
||||
break;
|
||||
case ')':
|
||||
if ($bInComment)
|
||||
{
|
||||
$iEndIndex = $iCurrentIndex;
|
||||
$sComment = \substr($sEmailAddress, $iStartIndex + 1, $iEndIndex - $iStartIndex - 1);
|
||||
$sEmailAddress = \substr_replace($sEmailAddress, '', $iStartIndex, $iEndIndex - $iStartIndex + 1);
|
||||
$iEndIndex = 0;
|
||||
$iCurrentIndex = 0;
|
||||
$iStartIndex = 0;
|
||||
$bInComment = false;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
$iCurrentIndex++;
|
||||
break;
|
||||
}
|
||||
|
||||
$iCurrentIndex++;
|
||||
}
|
||||
|
||||
if (\strlen($sEmail) === 0)
|
||||
{
|
||||
$aRegs = array('');
|
||||
if (\preg_match('/[^@\s]+@\S+/i', $sEmailAddress, $aRegs) && isset($aRegs[0]))
|
||||
{
|
||||
$sEmail = $aRegs[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sName = $sEmailAddress;
|
||||
}
|
||||
}
|
||||
|
||||
if ((\strlen($sEmail) > 0) && (\strlen($sName) == 0) && (\strlen($sComment) == 0))
|
||||
{
|
||||
$sName = \str_replace($sEmail, '', $sEmailAddress);
|
||||
}
|
||||
|
||||
$sEmail = \trim(\trim($sEmail), '<>');
|
||||
$sEmail = \rtrim(\trim($sEmail), '.');
|
||||
$sEmail = \trim($sEmail);
|
||||
|
||||
$sName = \trim(\trim($sName), '"');
|
||||
$sName = \trim($sName, '\'');
|
||||
$sComment = \trim(\trim($sComment), '()');
|
||||
|
||||
// Remove backslash
|
||||
$sName = \preg_replace('/\\\\(.)/s', '$1', $sName);
|
||||
$sComment = \preg_replace('/\\\\(.)/s', '$1', $sComment);
|
||||
|
||||
return Email::NewInstance($sEmail, $sName, $sComment);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetEmail($bIdn = false)
|
||||
{
|
||||
return $bIdn ? \MailSo\Base\Utils::IdnToUtf8($this->sEmail) : $this->sEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDisplayName()
|
||||
{
|
||||
return $this->sDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetRemark()
|
||||
{
|
||||
return $this->sRemark;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDkimStatus()
|
||||
{
|
||||
return $this->sDkimStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetDkimValue()
|
||||
{
|
||||
return $this->sDkimValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function GetAccountName()
|
||||
{
|
||||
return \MailSo\Base\Utils::GetAccountNameFromEmail($this->GetEmail(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function GetDomain($bIdn = false)
|
||||
{
|
||||
return \MailSo\Base\Utils::GetDomainFromEmail($this->GetEmail($bIdn));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sDkimStatus
|
||||
* @param string $sDkimValue = ''
|
||||
*/
|
||||
public function SetDkimStatusAndValue($sDkimStatus, $sDkimValue = '')
|
||||
{
|
||||
$this->sDkimStatus = \MailSo\Mime\Enumerations\DkimStatus::normalizeValue($sDkimStatus);
|
||||
$this->sDkimValue = $sDkimValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bIdn = false
|
||||
* @param bool $bDkim = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function ToArray($bIdn = false, $bDkim = true)
|
||||
{
|
||||
return $bDkim ? array($this->sDisplayName, $this->GetEmail($bIdn), $this->sRemark, $this->sDkimStatus, $this->sDkimValue) :
|
||||
array($this->sDisplayName, $this->GetEmail($bIdn), $this->sRemark);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $bConvertSpecialsName = false
|
||||
* @param bool $bIdn = false
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ToString($bConvertSpecialsName = false, $bIdn = false)
|
||||
{
|
||||
$sReturn = '';
|
||||
|
||||
$sRemark = \str_replace(')', '\)', $this->sRemark);
|
||||
$sDisplayName = \str_replace('"', '\"', $this->sDisplayName);
|
||||
|
||||
if ($bConvertSpecialsName)
|
||||
{
|
||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
|
||||
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||
$sDisplayName);
|
||||
|
||||
$sRemark = 0 === \strlen($sRemark) ? '' : \MailSo\Base\Utils::EncodeUnencodedValue(
|
||||
\MailSo\Base\Enumerations\Encoding::BASE64_SHORT,
|
||||
$sRemark);
|
||||
}
|
||||
|
||||
$sDisplayName = 0 === \strlen($sDisplayName) ? '' : '"'.$sDisplayName.'"';
|
||||
$sRemark = 0 === \strlen($sRemark) ? '' : '('.$sRemark.')';
|
||||
|
||||
if (0 < \strlen($this->sEmail))
|
||||
{
|
||||
$sReturn = $this->GetEmail($bIdn);
|
||||
if (0 < \strlen($sDisplayName.$sRemark))
|
||||
{
|
||||
$sReturn = $sDisplayName.' <'.$sReturn.'> '.$sRemark;
|
||||
}
|
||||
}
|
||||
|
||||
return \trim($sReturn);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
/Prem/**
|
||||
/_Prem/**
|
||||
|
|
@ -820,9 +820,9 @@ class Actions
|
|||
{
|
||||
if (null === $this->oPremProvider)
|
||||
{
|
||||
if (\file_exists(APP_VERSION_ROOT_PATH.'app/libraries/RainLoop/Prem/Provider.php'))
|
||||
if (\file_exists(APP_VERSION_ROOT_PATH.'app/libraries/RainLoop/Providers/Prem.php'))
|
||||
{
|
||||
$this->oPremProvider = new \RainLoop\Prem\Provider(
|
||||
$this->oPremProvider = new \RainLoop\Providers\Prem(
|
||||
$this->Config(), $this->Logger(), $this->Cacher(null, true)
|
||||
);
|
||||
}
|
||||
|
|
@ -1466,8 +1466,7 @@ class Actions
|
|||
'themes' => $this->GetThemes($bMobile, false),
|
||||
'languages' => $this->GetLanguages(false),
|
||||
'languagesAdmin' => $this->GetLanguages(true),
|
||||
'attachmentsActions' => $aAttachmentsActions,
|
||||
'openpgpPublicKeyServer' => $oConfig->Get('security', 'openpgp_public_key_server', '')
|
||||
'attachmentsActions' => $aAttachmentsActions
|
||||
), $bAdmin ? array(
|
||||
'adminHostUse' => '' !== $oConfig->Get('security', 'admin_panel_host', ''),
|
||||
'adminPath' => \strtolower($oConfig->Get('security', 'admin_panel_key', 'admin')),
|
||||
|
|
@ -2357,7 +2356,8 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
|||
$this->Logger()->AddSecret($sPassword);
|
||||
|
||||
if ('sleep@sleep.dev' === $sEmail && 0 < \strlen($sPassword) &&
|
||||
\is_numeric($sPassword) && $this->Config()->Get('debug', 'enable', false)
|
||||
\is_numeric($sPassword) && $this->Config()->Get('debug', 'enable', false) &&
|
||||
0 < (int) $sPassword && 30 > (int) $sPassword
|
||||
)
|
||||
{
|
||||
\sleep((int) $sPassword);
|
||||
|
|
@ -5179,8 +5179,11 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
|||
$aCache = array(
|
||||
|
||||
'Sent' => \MailSo\Imap\Enumerations\FolderType::SENT,
|
||||
|
||||
'Send' => \MailSo\Imap\Enumerations\FolderType::SENT,
|
||||
|
||||
'Outbox' => \MailSo\Imap\Enumerations\FolderType::SENT,
|
||||
'Out box' => \MailSo\Imap\Enumerations\FolderType::SENT,
|
||||
|
||||
'Sent Item' => \MailSo\Imap\Enumerations\FolderType::SENT,
|
||||
'Sent Items' => \MailSo\Imap\Enumerations\FolderType::SENT,
|
||||
'Send Item' => \MailSo\Imap\Enumerations\FolderType::SENT,
|
||||
|
|
@ -5199,6 +5202,7 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
|||
'Drafts Mails' => \MailSo\Imap\Enumerations\FolderType::DRAFTS,
|
||||
|
||||
'Spam' => \MailSo\Imap\Enumerations\FolderType::JUNK,
|
||||
'Spams' => \MailSo\Imap\Enumerations\FolderType::JUNK,
|
||||
|
||||
'Junk' => \MailSo\Imap\Enumerations\FolderType::JUNK,
|
||||
'Bulk Mail' => \MailSo\Imap\Enumerations\FolderType::JUNK,
|
||||
|
|
@ -5209,14 +5213,22 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
|||
'Bin' => \MailSo\Imap\Enumerations\FolderType::TRASH,
|
||||
|
||||
'Archive' => \MailSo\Imap\Enumerations\FolderType::ALL,
|
||||
'Archives' => \MailSo\Imap\Enumerations\FolderType::ALL,
|
||||
|
||||
'All' => \MailSo\Imap\Enumerations\FolderType::ALL,
|
||||
'All Mail' => \MailSo\Imap\Enumerations\FolderType::ALL,
|
||||
'All Mails' => \MailSo\Imap\Enumerations\FolderType::ALL,
|
||||
'AllMail' => \MailSo\Imap\Enumerations\FolderType::ALL,
|
||||
'AllMails' => \MailSo\Imap\Enumerations\FolderType::ALL,
|
||||
);
|
||||
|
||||
$aNewCache = array();
|
||||
foreach ($aCache as $sKey => $iType)
|
||||
{
|
||||
$aNewCache[$sKey] = $iType;
|
||||
$aNewCache[\str_replace(' ', '', $sKey)] = $iType;
|
||||
}
|
||||
|
||||
$aCache = $aNewCache;
|
||||
|
||||
$this->Plugins()->RunHook('filter.system-folders-names', array($oAccount, &$aCache));
|
||||
}
|
||||
|
||||
|
|
@ -8416,35 +8428,35 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
|||
case 1:
|
||||
break;
|
||||
|
||||
case 2: // horizontal flip
|
||||
case 2: // flip horizontal
|
||||
$oImage->flipHorizontally();
|
||||
break;
|
||||
|
||||
case 3: // 180 rotate left
|
||||
case 3: // rotate 180
|
||||
$oImage->rotate(180);
|
||||
break;
|
||||
|
||||
case 4: // vertical flip
|
||||
case 4: // flip vertical
|
||||
$oImage->flipVertically();
|
||||
break;
|
||||
|
||||
case 5: // vertical flip + 90 rotate right
|
||||
case 5: // vertical flip + 90 rotate
|
||||
$oImage->flipVertically();
|
||||
$oImage->rotate(-90);
|
||||
break;
|
||||
|
||||
case 6: // 90 rotate right
|
||||
$oImage->rotate(-90);
|
||||
break;
|
||||
|
||||
case 7: // horizontal flip + 90 rotate right
|
||||
$oImage->flipHorizontally();
|
||||
$oImage->rotate(-90);
|
||||
break;
|
||||
|
||||
case 8: // 90 rotate left
|
||||
$oImage->rotate(90);
|
||||
break;
|
||||
|
||||
case 6: // rotate 90
|
||||
$oImage->rotate(90);
|
||||
break;
|
||||
|
||||
case 7: // horizontal flip + 90 rotate
|
||||
$oImage->flipHorizontally();
|
||||
$oImage->rotate(90);
|
||||
break;
|
||||
|
||||
case 8: // rotate 270
|
||||
$oImage->rotate(270);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8586,8 +8598,6 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
|||
$self->cacheByKey($sRawKey);
|
||||
|
||||
$sLoadedData = null;
|
||||
$bDetectImageOrientation = false;
|
||||
|
||||
if (!$bDownload)
|
||||
{
|
||||
if ($bThumbnail)
|
||||
|
|
@ -9606,7 +9616,7 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
|||
private function hashFolderFullName($sFolderFullName)
|
||||
{
|
||||
return \in_array(\strtolower($sFolderFullName), array('inbox', 'sent', 'send', 'drafts',
|
||||
'spam', 'junk', 'bin', 'trash', 'archive', 'allmail')) ?
|
||||
'spam', 'junk', 'bin', 'trash', 'archive', 'allmail', 'all')) ?
|
||||
$sFolderFullName : \md5($sFolderFullName);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,273 +1,273 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Api
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function RunResult()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @staticvar bool $bOne
|
||||
* @return bool
|
||||
*/
|
||||
public static function Handle()
|
||||
{
|
||||
static $bOne = null;
|
||||
if (null === $bOne)
|
||||
{
|
||||
$bOne = \class_exists('MailSo\Version');
|
||||
if ($bOne)
|
||||
{
|
||||
\RainLoop\Api::SetupDefaultMailSoConfig();
|
||||
|
||||
$bOne = \RainLoop\Api::RunResult();
|
||||
}
|
||||
}
|
||||
|
||||
return $bOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Actions
|
||||
*/
|
||||
public static function Actions()
|
||||
{
|
||||
static $oActions = null;
|
||||
if (null === $oActions)
|
||||
{
|
||||
$oActions = \RainLoop\Actions::NewInstance();
|
||||
}
|
||||
|
||||
return $oActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Application
|
||||
*/
|
||||
public static function Config()
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Config();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \MailSo\Log\Logger
|
||||
*/
|
||||
public static function Logger()
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Logger();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function SetupDefaultMailSoConfig()
|
||||
{
|
||||
if (\class_exists('MailSo\Config'))
|
||||
{
|
||||
if (\RainLoop\Api::Config()->Get('labs', 'disable_iconv_if_mbstring_supported', false) &&
|
||||
\MailSo\Base\Utils::IsMbStringSupported() && \MailSo\Config::$MBSTRING)
|
||||
{
|
||||
\MailSo\Config::$ICONV = false;
|
||||
}
|
||||
|
||||
\MailSo\Config::$MessageListFastSimpleSearch =
|
||||
!!\RainLoop\Api::Config()->Get('labs', 'imap_message_list_fast_simple_search', true);
|
||||
|
||||
\MailSo\Config::$MessageListCountLimitTrigger =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_count_limit_trigger', 0);
|
||||
|
||||
\MailSo\Config::$MessageListDateFilter =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_date_filter', 0);
|
||||
|
||||
\MailSo\Config::$MessageListPermanentFilter =
|
||||
\trim(\RainLoop\Api::Config()->Get('labs', 'imap_message_list_permanent_filter', ''));
|
||||
|
||||
\MailSo\Config::$MessageAllHeaders =
|
||||
!!\RainLoop\Api::Config()->Get('labs', 'imap_message_all_headers', false);
|
||||
|
||||
\MailSo\Config::$LargeThreadLimit =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_large_thread_limit', 50);
|
||||
|
||||
\MailSo\Config::$ImapTimeout =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_timeout', 300);
|
||||
|
||||
\MailSo\Config::$BoundaryPrefix = '_RainLoop_';
|
||||
|
||||
\MailSo\Config::$SystemLogger = \RainLoop\Api::Logger();
|
||||
|
||||
$sSslCafile = \RainLoop\Api::Config()->Get('ssl', 'cafile', '');
|
||||
$sSslCapath = \RainLoop\Api::Config()->Get('ssl', 'capath', '');
|
||||
|
||||
\RainLoop\Utils::$CookieDefaultPath = \RainLoop\Api::Config()->Get('labs', 'cookie_default_path', '');
|
||||
if (\RainLoop\Api::Config()->Get('labs', 'cookie_default_secure', false))
|
||||
{
|
||||
\RainLoop\Utils::$CookieDefaultSecure = true;
|
||||
}
|
||||
|
||||
if (!empty($sSslCafile) || !empty($sSslCapath))
|
||||
{
|
||||
\MailSo\Hooks::Add('Net.NetClient.StreamContextSettings/Filter', function (&$aStreamContextSettings) use ($sSslCafile, $sSslCapath) {
|
||||
if (isset($aStreamContextSettings['ssl']) && \is_array($aStreamContextSettings['ssl']))
|
||||
{
|
||||
if (empty($aStreamContextSettings['ssl']['cafile']) && !empty($sSslCafile))
|
||||
{
|
||||
$aStreamContextSettings['ssl']['cafile'] = $sSslCafile;
|
||||
}
|
||||
|
||||
if (empty($aStreamContextSettings['ssl']['capath']) && !empty($sSslCapath))
|
||||
{
|
||||
$aStreamContextSettings['ssl']['capath'] = $sSslCapath;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
\MailSo\Config::$HtmlStrictDebug = !!\RainLoop\Api::Config()->Get('debug', 'enable', false);
|
||||
|
||||
if (\RainLoop\Api::Config()->Get('labs', 'strict_html_parser', true))
|
||||
{
|
||||
\MailSo\Config::$HtmlStrictAllowedAttributes = array(
|
||||
// rainloop
|
||||
'data-wrp',
|
||||
// defaults
|
||||
'name',
|
||||
'dir', 'lang', 'style', 'title',
|
||||
'background', 'bgcolor', 'alt', 'height', 'width', 'src', 'href',
|
||||
'border', 'bordercolor', 'charset', 'direction', 'language',
|
||||
// a
|
||||
'coords', 'download', 'hreflang', 'shape',
|
||||
// body
|
||||
'alink', 'bgproperties', 'bottommargin', 'leftmargin', 'link', 'rightmargin', 'text', 'topmargin', 'vlink',
|
||||
'marginwidth', 'marginheight', 'offset',
|
||||
// button,
|
||||
'disabled', 'type', 'value',
|
||||
// col
|
||||
'align', 'valign',
|
||||
// font
|
||||
'color', 'face', 'size',
|
||||
// form
|
||||
'novalidate',
|
||||
// hr
|
||||
'noshade',
|
||||
// img
|
||||
'hspace', 'sizes', 'srcset', 'vspace', 'usemap',
|
||||
// input, textarea
|
||||
'checked', 'max', 'min', 'maxlength', 'multiple', 'pattern', 'placeholder', 'readonly', 'required', 'step', 'wrap',
|
||||
// label
|
||||
'for',
|
||||
// meter
|
||||
'low', 'high', 'optimum',
|
||||
// ol
|
||||
'reversed', 'start',
|
||||
// option
|
||||
'selected', 'label',
|
||||
// table
|
||||
'cols', 'rows', 'frame', 'rules', 'summary', 'cellpadding', 'cellspacing',
|
||||
// td
|
||||
'abbr', 'axis', 'colspan', 'rowspan', 'headers', 'nowrap'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function Version()
|
||||
{
|
||||
return APP_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sPassword
|
||||
* @param array $aAdditionalOptions = array()
|
||||
* @param bool $bUseTimeout = true
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function GetUserSsoHash($sEmail, $sPassword, $aAdditionalOptions = array(), $bUseTimeout = true)
|
||||
{
|
||||
$sSsoHash = \MailSo\Base\Utils::Sha1Rand($sEmail.$sPassword);
|
||||
|
||||
return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash),
|
||||
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'Email' => $sEmail,
|
||||
'Password' => $sPassword,
|
||||
'AdditionalOptions' => $aAdditionalOptions,
|
||||
'Time' => $bUseTimeout ? \time() : 0
|
||||
))) ? $sSsoHash : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSsoHash
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ClearUserSsoHash($sSsoHash)
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Cacher()->Delete(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ClearUserData($sEmail)
|
||||
{
|
||||
if (0 < \strlen($sEmail))
|
||||
{
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail);
|
||||
|
||||
$oStorageProvider = \RainLoop\Api::Actions()->StorageProvider();
|
||||
if ($oStorageProvider && $oStorageProvider->IsActive())
|
||||
{
|
||||
$oStorageProvider->DeleteStorage($sEmail);
|
||||
}
|
||||
|
||||
if (\RainLoop\Api::Actions()->AddressBookProvider() &&
|
||||
\RainLoop\Api::Actions()->AddressBookProvider()->IsActive())
|
||||
{
|
||||
\RainLoop\Api::Actions()->AddressBookProvider()->DeleteAllContacts($sEmail);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function LogoutCurrentLogginedUser()
|
||||
{
|
||||
\RainLoop\Utils::ClearCookie('rlsession');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function ExitOnEnd()
|
||||
{
|
||||
if (!\defined('RAINLOOP_EXIT_ON_END'))
|
||||
{
|
||||
\define('RAINLOOP_EXIT_ON_END', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace RainLoop;
|
||||
|
||||
class Api
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function RunResult()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @staticvar bool $bOne
|
||||
* @return bool
|
||||
*/
|
||||
public static function Handle()
|
||||
{
|
||||
static $bOne = null;
|
||||
if (null === $bOne)
|
||||
{
|
||||
$bOne = \class_exists('MailSo\Version');
|
||||
if ($bOne)
|
||||
{
|
||||
\RainLoop\Api::SetupDefaultMailSoConfig();
|
||||
|
||||
$bOne = \RainLoop\Api::RunResult();
|
||||
}
|
||||
}
|
||||
|
||||
return $bOne;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Actions
|
||||
*/
|
||||
public static function Actions()
|
||||
{
|
||||
static $oActions = null;
|
||||
if (null === $oActions)
|
||||
{
|
||||
$oActions = \RainLoop\Actions::NewInstance();
|
||||
}
|
||||
|
||||
return $oActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \RainLoop\Application
|
||||
*/
|
||||
public static function Config()
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Config();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \MailSo\Log\Logger
|
||||
*/
|
||||
public static function Logger()
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Logger();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function SetupDefaultMailSoConfig()
|
||||
{
|
||||
if (\class_exists('MailSo\Config'))
|
||||
{
|
||||
if (\RainLoop\Api::Config()->Get('labs', 'disable_iconv_if_mbstring_supported', false) &&
|
||||
\MailSo\Base\Utils::IsMbStringSupported() && \MailSo\Config::$MBSTRING)
|
||||
{
|
||||
\MailSo\Config::$ICONV = false;
|
||||
}
|
||||
|
||||
\MailSo\Config::$MessageListFastSimpleSearch =
|
||||
!!\RainLoop\Api::Config()->Get('labs', 'imap_message_list_fast_simple_search', true);
|
||||
|
||||
\MailSo\Config::$MessageListCountLimitTrigger =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_count_limit_trigger', 0);
|
||||
|
||||
\MailSo\Config::$MessageListDateFilter =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_date_filter', 0);
|
||||
|
||||
\MailSo\Config::$MessageListPermanentFilter =
|
||||
\trim(\RainLoop\Api::Config()->Get('labs', 'imap_message_list_permanent_filter', ''));
|
||||
|
||||
\MailSo\Config::$MessageAllHeaders =
|
||||
!!\RainLoop\Api::Config()->Get('labs', 'imap_message_all_headers', false);
|
||||
|
||||
\MailSo\Config::$LargeThreadLimit =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_large_thread_limit', 50);
|
||||
|
||||
\MailSo\Config::$ImapTimeout =
|
||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_timeout', 300);
|
||||
|
||||
\MailSo\Config::$BoundaryPrefix = '_RainLoop_';
|
||||
|
||||
\MailSo\Config::$SystemLogger = \RainLoop\Api::Logger();
|
||||
|
||||
$sSslCafile = \RainLoop\Api::Config()->Get('ssl', 'cafile', '');
|
||||
$sSslCapath = \RainLoop\Api::Config()->Get('ssl', 'capath', '');
|
||||
|
||||
\RainLoop\Utils::$CookieDefaultPath = \RainLoop\Api::Config()->Get('labs', 'cookie_default_path', '');
|
||||
if (\RainLoop\Api::Config()->Get('labs', 'cookie_default_secure', false))
|
||||
{
|
||||
\RainLoop\Utils::$CookieDefaultSecure = true;
|
||||
}
|
||||
|
||||
if (!empty($sSslCafile) || !empty($sSslCapath))
|
||||
{
|
||||
\MailSo\Hooks::Add('Net.NetClient.StreamContextSettings/Filter', function (&$aStreamContextSettings) use ($sSslCafile, $sSslCapath) {
|
||||
if (isset($aStreamContextSettings['ssl']) && \is_array($aStreamContextSettings['ssl']))
|
||||
{
|
||||
if (empty($aStreamContextSettings['ssl']['cafile']) && !empty($sSslCafile))
|
||||
{
|
||||
$aStreamContextSettings['ssl']['cafile'] = $sSslCafile;
|
||||
}
|
||||
|
||||
if (empty($aStreamContextSettings['ssl']['capath']) && !empty($sSslCapath))
|
||||
{
|
||||
$aStreamContextSettings['ssl']['capath'] = $sSslCapath;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
\MailSo\Config::$HtmlStrictDebug = !!\RainLoop\Api::Config()->Get('debug', 'enable', false);
|
||||
|
||||
if (\RainLoop\Api::Config()->Get('labs', 'strict_html_parser', true))
|
||||
{
|
||||
\MailSo\Config::$HtmlStrictAllowedAttributes = array(
|
||||
// rainloop
|
||||
'data-wrp',
|
||||
// defaults
|
||||
'name',
|
||||
'dir', 'lang', 'style', 'title',
|
||||
'background', 'bgcolor', 'alt', 'height', 'width', 'src', 'href',
|
||||
'border', 'bordercolor', 'charset', 'direction', 'language',
|
||||
// a
|
||||
'coords', 'download', 'hreflang', 'shape',
|
||||
// body
|
||||
'alink', 'bgproperties', 'bottommargin', 'leftmargin', 'link', 'rightmargin', 'text', 'topmargin', 'vlink',
|
||||
'marginwidth', 'marginheight', 'offset',
|
||||
// button,
|
||||
'disabled', 'type', 'value',
|
||||
// col
|
||||
'align', 'valign',
|
||||
// font
|
||||
'color', 'face', 'size',
|
||||
// form
|
||||
'novalidate',
|
||||
// hr
|
||||
'noshade',
|
||||
// img
|
||||
'hspace', 'sizes', 'srcset', 'vspace', 'usemap',
|
||||
// input, textarea
|
||||
'checked', 'max', 'min', 'maxlength', 'multiple', 'pattern', 'placeholder', 'readonly', 'required', 'step', 'wrap',
|
||||
// label
|
||||
'for',
|
||||
// meter
|
||||
'low', 'high', 'optimum',
|
||||
// ol
|
||||
'reversed', 'start',
|
||||
// option
|
||||
'selected', 'label',
|
||||
// table
|
||||
'cols', 'rows', 'frame', 'rules', 'summary', 'cellpadding', 'cellspacing',
|
||||
// td
|
||||
'abbr', 'axis', 'colspan', 'rowspan', 'headers', 'nowrap'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function Version()
|
||||
{
|
||||
return APP_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
* @param string $sPassword
|
||||
* @param array $aAdditionalOptions = array()
|
||||
* @param bool $bUseTimeout = true
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function GetUserSsoHash($sEmail, $sPassword, $aAdditionalOptions = array(), $bUseTimeout = true)
|
||||
{
|
||||
$sSsoHash = \MailSo\Base\Utils::Sha1Rand(\md5($sEmail).\md5($sPassword));
|
||||
|
||||
return \RainLoop\Api::Actions()->Cacher()->Set(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash),
|
||||
\RainLoop\Utils::EncodeKeyValuesQ(array(
|
||||
'Email' => $sEmail,
|
||||
'Password' => $sPassword,
|
||||
'AdditionalOptions' => $aAdditionalOptions,
|
||||
'Time' => $bUseTimeout ? \time() : 0
|
||||
))) ? $sSsoHash : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSsoHash
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ClearUserSsoHash($sSsoHash)
|
||||
{
|
||||
return \RainLoop\Api::Actions()->Cacher()->Delete(\RainLoop\KeyPathHelper::SsoCacherKey($sSsoHash));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sEmail
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function ClearUserData($sEmail)
|
||||
{
|
||||
if (0 < \strlen($sEmail))
|
||||
{
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail);
|
||||
|
||||
$oStorageProvider = \RainLoop\Api::Actions()->StorageProvider();
|
||||
if ($oStorageProvider && $oStorageProvider->IsActive())
|
||||
{
|
||||
$oStorageProvider->DeleteStorage($sEmail);
|
||||
}
|
||||
|
||||
if (\RainLoop\Api::Actions()->AddressBookProvider() &&
|
||||
\RainLoop\Api::Actions()->AddressBookProvider()->IsActive())
|
||||
{
|
||||
\RainLoop\Api::Actions()->AddressBookProvider()->DeleteAllContacts($sEmail);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function LogoutCurrentLogginedUser()
|
||||
{
|
||||
\RainLoop\Utils::ClearCookie('rlsession');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public static function ExitOnEnd()
|
||||
{
|
||||
if (!\defined('RAINLOOP_EXIT_ON_END'))
|
||||
{
|
||||
\define('RAINLOOP_EXIT_ON_END', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,7 +200,6 @@ class Application extends \RainLoop\Config\AbstractConfig
|
|||
'x_frame_options_header' => array(''),
|
||||
|
||||
'openpgp' => array(false),
|
||||
'openpgp_public_key_server' => array(''),
|
||||
|
||||
'admin_login' => array('admin', 'Login and password for web admin panel'),
|
||||
'admin_password' => array('12345'),
|
||||
|
|
|
|||
|
|
@ -1,404 +1,410 @@
|
|||
<?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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param bool $bCheckAliases = true
|
||||
*
|
||||
* @return \RainLoop\Model\Domain|null
|
||||
*/
|
||||
public function Load($sName, $bFindWithWildCard = false, $bCheckDisabled = true, $bCheckAliases = 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');
|
||||
// if ($bCheckAliases && !empty($aDomain['alias']))
|
||||
// {
|
||||
// $oDomain = $this->Load($aDomain['alias'], false, false, false);
|
||||
// if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain)
|
||||
// {
|
||||
// $oDomain->SetAliasName($sName);
|
||||
// }
|
||||
//
|
||||
// return $oDomain;
|
||||
// }
|
||||
|
||||
// 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 ($bCheckAliases && \file_exists($this->sDomainPath.'/'.$sRealFileName.'.alias') &&
|
||||
(!$bCheckDisabled || 0 === \strlen($sDisabled) || false === \strpos(','.$sDisabled.',', ','.\MailSo\Base\Utils::IdnToAscii($sName, true).',')))
|
||||
{
|
||||
$sAlias = \trim(\file_get_contents($this->sDomainPath.'/'.$sRealFileName.'.alias'));
|
||||
if (!empty($sAlias))
|
||||
{
|
||||
$oDomain = $this->Load($sAlias, false, false, false);
|
||||
if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain)
|
||||
{
|
||||
$oDomain->SetAliasName($sName);
|
||||
}
|
||||
|
||||
return $oDomain;
|
||||
}
|
||||
}
|
||||
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
|
||||
* @param string $sAlias
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function SaveAlias($sName, $sAlias)
|
||||
{
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$this->oCacher->Delete($this->wildcardDomainsCacheKey());
|
||||
}
|
||||
|
||||
$mResult = \file_put_contents($this->sDomainPath.'/'.$sRealFileName.'.alias', $sAlias);
|
||||
return \is_int($mResult) && 0 < $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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), ', '));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Delete($sName)
|
||||
{
|
||||
$bResult = true;
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if (0 < \strlen($sName))
|
||||
{
|
||||
if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini'))
|
||||
{
|
||||
$bResult = \unlink($this->sDomainPath.'/'.$sRealFileName.'.ini');
|
||||
}
|
||||
else if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.alias'))
|
||||
{
|
||||
$bResult = \unlink($this->sDomainPath.'/'.$sRealFileName.'.alias');
|
||||
}
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
{
|
||||
$this->Disable($sName, false);
|
||||
}
|
||||
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$this->oCacher->Delete($this->wildcardDomainsCacheKey());
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iOffset = 0
|
||||
* @param int $iLimit = 20
|
||||
* @param int $sSearch = ''
|
||||
* @param bool $bIncludeAliases = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetList($iOffset = 0, $iLimit = 20, $sSearch = '', $bIncludeAliases = true)
|
||||
{
|
||||
$aResult = array();
|
||||
$aWildCards = array();
|
||||
$aAliases = array();
|
||||
|
||||
$aList = \glob($this->sDomainPath.'/*.{ini,alias}', GLOB_BRACE);
|
||||
|
||||
foreach ($aList as $sFile)
|
||||
{
|
||||
$sName = \basename($sFile);
|
||||
$bAlias = '.alias' === \substr($sName, -6);
|
||||
|
||||
$sName = \preg_replace('/\.(ini|alias)$/', '', $sName);
|
||||
$sName = $this->codeFileName($sName, true);
|
||||
|
||||
if ($bAlias)
|
||||
{
|
||||
if ($bIncludeAliases)
|
||||
{
|
||||
$aAliases[] = $sName;
|
||||
}
|
||||
}
|
||||
else if (false !== \strpos($sName, '*'))
|
||||
{
|
||||
$aWildCards[] = $sName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult[] = $sName;
|
||||
}
|
||||
}
|
||||
|
||||
\sort($aResult, SORT_STRING);
|
||||
\sort($aAliases, SORT_STRING);
|
||||
\rsort($aWildCards, SORT_STRING);
|
||||
|
||||
$aResult = \array_merge($aResult, $aAliases, $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] = array(
|
||||
!\in_array($sName, $aDisabledNames),
|
||||
\in_array($sName, $aAliases)
|
||||
);
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch = ''
|
||||
* @param bool $bIncludeAliases = true
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function Count($sSearch = '', $bIncludeAliases = true)
|
||||
{
|
||||
return \count($this->GetList(0, 999, $sSearch, $bIncludeAliases));
|
||||
}
|
||||
<?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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
* @param bool $bCheckAliases = true
|
||||
*
|
||||
* @return \RainLoop\Model\Domain|null
|
||||
*/
|
||||
public function Load($sName, $bFindWithWildCard = false, $bCheckDisabled = true, $bCheckAliases = 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');
|
||||
// if ($bCheckAliases && !empty($aDomain['alias']))
|
||||
// {
|
||||
// $oDomain = $this->Load($aDomain['alias'], false, false, false);
|
||||
// if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain)
|
||||
// {
|
||||
// $oDomain->SetAliasName($sName);
|
||||
// }
|
||||
//
|
||||
// return $oDomain;
|
||||
// }
|
||||
|
||||
// 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 ($bCheckAliases && \file_exists($this->sDomainPath.'/'.$sRealFileName.'.alias') &&
|
||||
(!$bCheckDisabled || 0 === \strlen($sDisabled) || false === \strpos(','.$sDisabled.',', ','.\MailSo\Base\Utils::IdnToAscii($sName, true).',')))
|
||||
{
|
||||
$sAlias = \trim(\file_get_contents($this->sDomainPath.'/'.$sRealFileName.'.alias'));
|
||||
if (!empty($sAlias))
|
||||
{
|
||||
$oDomain = $this->Load($sAlias, false, false, false);
|
||||
if ($oDomain && $oDomain instanceof \RainLoop\Model\Domain)
|
||||
{
|
||||
$oDomain->SetAliasName($sName);
|
||||
}
|
||||
|
||||
return $oDomain;
|
||||
}
|
||||
}
|
||||
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
|
||||
* @param string $sAlias
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function SaveAlias($sName, $sAlias)
|
||||
{
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$this->oCacher->Delete($this->wildcardDomainsCacheKey());
|
||||
}
|
||||
|
||||
$mResult = \file_put_contents($this->sDomainPath.'/'.$sRealFileName.'.alias', $sAlias);
|
||||
return \is_int($mResult) && 0 < $mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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), ', '));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Delete($sName)
|
||||
{
|
||||
$bResult = true;
|
||||
$sRealFileName = $this->codeFileName($sName);
|
||||
|
||||
if (0 < \strlen($sName))
|
||||
{
|
||||
if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.ini'))
|
||||
{
|
||||
$bResult = \unlink($this->sDomainPath.'/'.$sRealFileName.'.ini');
|
||||
}
|
||||
else if (\file_exists($this->sDomainPath.'/'.$sRealFileName.'.alias'))
|
||||
{
|
||||
$bResult = \unlink($this->sDomainPath.'/'.$sRealFileName.'.alias');
|
||||
}
|
||||
}
|
||||
|
||||
if ($bResult)
|
||||
{
|
||||
$this->Disable($sName, false);
|
||||
}
|
||||
|
||||
if ($this->oCacher)
|
||||
{
|
||||
$this->oCacher->Delete($this->wildcardDomainsCacheKey());
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $iOffset = 0
|
||||
* @param int $iLimit = 20
|
||||
* @param int $sSearch = ''
|
||||
* @param bool $bIncludeAliases = true
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetList($iOffset = 0, $iLimit = 20, $sSearch = '', $bIncludeAliases = true)
|
||||
{
|
||||
$aResult = array();
|
||||
$aWildCards = array();
|
||||
$aAliases = array();
|
||||
|
||||
// $aList = \glob($this->sDomainPath.'/*.{ini,alias}', GLOB_BRACE);
|
||||
$aList = @\array_diff(\scandir($this->sDomainPath), array('.', '..'));
|
||||
if (\is_array($aList))
|
||||
{
|
||||
foreach ($aList as $sFile)
|
||||
{
|
||||
$sName = $sFile;
|
||||
if ('.ini' === \substr($sName, -4) || '.alias' === \substr($sName, -6))
|
||||
{
|
||||
$bAlias = '.alias' === \substr($sName, -6);
|
||||
|
||||
$sName = \preg_replace('/\.(ini|alias)$/', '', $sName);
|
||||
$sName = $this->codeFileName($sName, true);
|
||||
|
||||
if ($bAlias)
|
||||
{
|
||||
if ($bIncludeAliases)
|
||||
{
|
||||
$aAliases[] = $sName;
|
||||
}
|
||||
}
|
||||
else if (false !== \strpos($sName, '*'))
|
||||
{
|
||||
$aWildCards[] = $sName;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult[] = $sName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\sort($aResult, SORT_STRING);
|
||||
\sort($aAliases, SORT_STRING);
|
||||
\rsort($aWildCards, SORT_STRING);
|
||||
|
||||
$aResult = \array_merge($aResult, $aAliases, $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] = array(
|
||||
!\in_array($sName, $aDisabledNames),
|
||||
\in_array($sName, $aAliases)
|
||||
);
|
||||
}
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sSearch = ''
|
||||
* @param bool $bIncludeAliases = true
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function Count($sSearch = '', $bIncludeAliases = true)
|
||||
{
|
||||
return \count($this->GetList(0, 999, $sSearch, $bIncludeAliases));
|
||||
}
|
||||
}
|
||||
392
rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Prem.php
Normal file
392
rainloop/v/0.0.0/app/libraries/RainLoop/Providers/Prem.php
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
<?php
|
||||
|
||||
namespace RainLoop\Providers;
|
||||
|
||||
class Prem
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($oConfig, $oLogger, $oCacher)
|
||||
{
|
||||
$this->oConfig = $oConfig;
|
||||
$this->oLogger = $oLogger;
|
||||
$this->oCacher = $oCacher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function Type()
|
||||
{
|
||||
static $bResult = null;
|
||||
if (null === $bResult)
|
||||
{
|
||||
$bResult = $this->Parser($this->Fetcher(false, true));
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function IsActive()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sInput
|
||||
* @param int $iExpired = 0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function Parser($sInput, &$iExpired = 0)
|
||||
{
|
||||
$aMatch = array();
|
||||
if (\preg_match('/^EXPIRED:([\d]+)$/', $sInput, $aMatch))
|
||||
{
|
||||
$iExpired = (int) $aMatch[1];
|
||||
return \time() < $iExpired;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aAppData
|
||||
*/
|
||||
public function PopulateAppData(&$aAppData)
|
||||
{
|
||||
if (\is_array($aAppData))
|
||||
{
|
||||
$aAppData['Community'] = false;
|
||||
|
||||
$oConfig = $this->oConfig;
|
||||
if ($oConfig && $this->Type())
|
||||
{
|
||||
$aAppData['PremType'] = true;
|
||||
$aAppData['LoginLogo'] = $oConfig->Get('branding', 'login_logo', '');
|
||||
$aAppData['LoginBackground'] = $oConfig->Get('branding', 'login_background', '');
|
||||
$aAppData['LoginCss'] = $oConfig->Get('branding', 'login_css', '');
|
||||
$aAppData['LoginDescription'] = $oConfig->Get('branding', 'login_desc', '');
|
||||
$aAppData['LoginPowered'] = !!$oConfig->Get('branding', 'login_powered', true);
|
||||
$aAppData['UserLogo'] = $oConfig->Get('branding', 'user_logo', '');
|
||||
$aAppData['UserLogoTitle'] = $oConfig->Get('branding', 'user_logo_title', '');
|
||||
$aAppData['UserLogoMessage'] = $oConfig->Get('branding', 'user_logo_message', '');
|
||||
$aAppData['UserIframeMessage'] = $oConfig->Get('branding', 'user_iframe_message', '');
|
||||
$aAppData['UserCss'] = $oConfig->Get('branding', 'user_css', '');
|
||||
$aAppData['WelcomePageUrl'] = $oConfig->Get('branding', 'welcome_page_url', '');
|
||||
$aAppData['WelcomePageDisplay'] = \strtolower($oConfig->Get('branding', 'welcome_page_display', 'none'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function PremSection(&$oActions, &$oConfig)
|
||||
{
|
||||
if ($oActions && $oActions->HasOneOfActionParams(array(
|
||||
'LoginLogo', 'LoginBackground', 'LoginDescription', 'LoginCss', 'LoginPowered',
|
||||
'UserLogo', 'UserLogoTitle', 'UserLogoMessage', 'UserIframeMessage', 'UserCss',
|
||||
'WelcomePageUrl', 'WelcomePageDisplay'
|
||||
)) && $this->Type())
|
||||
{
|
||||
$oActions->setConfigFromParams($oConfig, 'LoginLogo', 'branding', 'login_logo', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'LoginBackground', 'branding', 'login_background', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'LoginDescription', 'branding', 'login_desc', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'LoginCss', 'branding', 'login_css', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'LoginPowered', 'branding', 'login_powered', 'bool');
|
||||
|
||||
$oActions->setConfigFromParams($oConfig, 'UserLogo', 'branding', 'user_logo', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'UserLogoTitle', 'branding', 'user_logo_title', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'UserLogoMessage', 'branding', 'user_logo_message', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'UserIframeMessage', 'branding', 'user_iframe_message', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'UserCss', 'branding', 'user_css', 'string');
|
||||
|
||||
$oActions->setConfigFromParams($oConfig, 'WelcomePageUrl', 'branding', 'welcome_page_url', 'string');
|
||||
$oActions->setConfigFromParams($oConfig, 'WelcomePageDisplay', 'branding', 'welcome_page_display', 'string');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Activate($sDomain, $sKey, &$iCode)
|
||||
{
|
||||
$iCode = 0;
|
||||
$sContentType = '';
|
||||
|
||||
$oHttp = \MailSo\Base\Http::SingletonInstance();
|
||||
|
||||
$sResult = $oHttp->GetUrlAsString(APP_API_PATH.'activate/'.\urlencode($sDomain).'/'.\urlencode($sKey),
|
||||
'RainLoop/'.APP_VERSION, $sContentType, $iCode, $this->oLogger, 10,
|
||||
$this->oConfig->Get('labs', 'curl_proxy', ''), $this->oConfig->Get('labs', 'curl_proxy_auth', ''),
|
||||
array(), false
|
||||
);
|
||||
|
||||
if (200 !== $iCode)
|
||||
{
|
||||
$sResult = '';
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function Fetcher($sForce = false, $bLongCache = false, $iFastCacheTimeInMin = 10, $iLongCacheTimeInDays = 3)
|
||||
{
|
||||
$sDomain = \trim(APP_SITE);
|
||||
|
||||
$oConfig = $this->oConfig;
|
||||
$oLogger = $this->oLogger;
|
||||
$oCacher = $this->oCacher;
|
||||
|
||||
$oHttp = \MailSo\Base\Http::SingletonInstance();
|
||||
|
||||
if (0 === \strlen($sDomain) || $oHttp->CheckLocalhost($sDomain) || !$oCacher || !$oConfig || !$oCacher->Verify(true))
|
||||
{
|
||||
return 'NO';
|
||||
}
|
||||
|
||||
$sDomainKeyValue = \RainLoop\KeyPathHelper::LicensingDomainKeyValue($sDomain);
|
||||
$sDomainLongKeyValue = \RainLoop\KeyPathHelper::LicensingDomainKeyOtherValue($sDomain);
|
||||
|
||||
$sValue = '';
|
||||
if (!$sForce)
|
||||
{
|
||||
if ($bLongCache)
|
||||
{
|
||||
$bLock = $oCacher->GetLock($sDomainLongKeyValue);
|
||||
$iTime = $bLock ? 0 : $oCacher->GetTimer($sDomainLongKeyValue);
|
||||
|
||||
if ($bLock || (0 < $iTime && \time() < $iTime + (60 * 60 * 24) * $iLongCacheTimeInDays))
|
||||
{
|
||||
$sValue = $oCacher->Get($sDomainLongKeyValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$iTime = $oCacher->GetTimer($sDomainKeyValue);
|
||||
if (0 < $iTime && \time() < $iTime + 60 * $iFastCacheTimeInMin)
|
||||
{
|
||||
$sValue = $oCacher->Get($sDomainKeyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === \strlen($sValue))
|
||||
{
|
||||
if ($bLongCache)
|
||||
{
|
||||
if (!$oCacher->SetTimer($sDomainLongKeyValue))
|
||||
{
|
||||
return 'NO';
|
||||
}
|
||||
|
||||
$oCacher->SetLock($sDomainLongKeyValue);
|
||||
}
|
||||
|
||||
$iCode = 0;
|
||||
$sContentType = '';
|
||||
|
||||
$sValue = $oHttp->GetUrlAsString(APP_API_PATH.'status/'.\urlencode($sDomain),
|
||||
'RainLoop/'.APP_VERSION, $sContentType, $iCode, $oLogger, 5,
|
||||
$oConfig->Get('labs', 'curl_proxy', ''), $oConfig->Get('labs', 'curl_proxy_auth', ''),
|
||||
array(), false
|
||||
);
|
||||
|
||||
if ($oLogger)
|
||||
{
|
||||
$oLogger->Write($sValue);
|
||||
}
|
||||
|
||||
if (404 === $iCode)
|
||||
{
|
||||
$sValue = 'NO';
|
||||
}
|
||||
else if (200 !== $iCode)
|
||||
{
|
||||
$sValue = '';
|
||||
}
|
||||
|
||||
$oCacher->SetTimer($sDomainKeyValue);
|
||||
|
||||
$oCacher->Set($sDomainKeyValue, $sValue);
|
||||
$oCacher->Set($sDomainLongKeyValue, $sValue);
|
||||
|
||||
if ($bLongCache)
|
||||
{
|
||||
$oCacher->RemoveLock($sDomainLongKeyValue);
|
||||
}
|
||||
}
|
||||
|
||||
return $sValue;
|
||||
}
|
||||
|
||||
public function ClearOldVersion()
|
||||
{
|
||||
$sVPath = APP_INDEX_ROOT_PATH.'rainloop/v/';
|
||||
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Versions GC: Begin');
|
||||
}
|
||||
|
||||
$aDirs = @\array_map('basename', @\array_filter(@\glob($sVPath.'*'), 'is_dir'));
|
||||
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Versions GC: Count:'.(\is_array($aDirs) ? \count($aDirs) : 0));
|
||||
}
|
||||
|
||||
if (\is_array($aDirs) && 5 < \count($aDirs))
|
||||
{
|
||||
\uasort($aDirs, 'version_compare');
|
||||
|
||||
foreach ($aDirs as $sName)
|
||||
{
|
||||
if (APP_DEV_VERSION !== $sName && APP_VERSION !== $sName)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Versions GC: Begin to remove "'.$sVPath.$sName.'" version');
|
||||
}
|
||||
|
||||
if (@\unlink($sVPath.$sName.'/index.php'))
|
||||
{
|
||||
@\MailSo\Base\Utils::RecRmDir($sVPath.$sName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Versions GC (Error): index file cant be removed from"'.$sVPath.$sName.'"',
|
||||
\MailSo\Log\Enumerations\Type::ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Versions GC: End to remove "'.$sVPath.$sName.'" version');
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Versions GC: End');
|
||||
}
|
||||
}
|
||||
|
||||
public function UpdateCore($oActions, $sFile)
|
||||
{
|
||||
$bResult = false;
|
||||
|
||||
$sNewVersion = '';
|
||||
$sTmp = $oActions->downloadRemotePackageByUrl($sFile);
|
||||
if (!empty($sTmp))
|
||||
{
|
||||
include_once APP_VERSION_ROOT_PATH.'app/libraries/pclzip/pclzip.lib.php';
|
||||
|
||||
$oArchive = new \PclZip($sTmp);
|
||||
$sTmpFolder = APP_PRIVATE_DATA.\md5($sTmp);
|
||||
|
||||
\mkdir($sTmpFolder);
|
||||
if (\is_dir($sTmpFolder))
|
||||
{
|
||||
$bResult = 0 !== $oArchive->extract(PCLZIP_OPT_PATH, $sTmpFolder);
|
||||
if (!$bResult)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Cannot extract package files: '.$oArchive->errorInfo(), \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||
}
|
||||
}
|
||||
|
||||
if ($bResult && \file_exists($sTmpFolder.'/index.php') &&
|
||||
\is_writable(APP_INDEX_ROOT_PATH.'rainloop/') &&
|
||||
\is_writable(APP_INDEX_ROOT_PATH.'index.php') &&
|
||||
\is_dir($sTmpFolder.'/rainloop/'))
|
||||
{
|
||||
$aMatch = array();
|
||||
$sIndexFile = \file_get_contents($sTmpFolder.'/index.php');
|
||||
if (\preg_match('/\'APP_VERSION\', \'([^\']+)\'/', $sIndexFile, $aMatch) && !empty($aMatch[1]))
|
||||
{
|
||||
$sNewVersion = \trim($aMatch[1]);
|
||||
}
|
||||
|
||||
if (empty($sNewVersion))
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Unknown version', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||
}
|
||||
}
|
||||
else if (!\is_dir(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion))
|
||||
{
|
||||
\MailSo\Base\Utils::CopyDir($sTmpFolder.'/rainloop/', APP_INDEX_ROOT_PATH.'rainloop/');
|
||||
|
||||
if (\is_dir(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion) &&
|
||||
\is_file(APP_INDEX_ROOT_PATH.'rainloop/v/'.$sNewVersion.'/index.php'))
|
||||
{
|
||||
$bResult = \copy($sTmpFolder.'/index.php', APP_INDEX_ROOT_PATH.'index.php');
|
||||
|
||||
if ($bResult)
|
||||
{
|
||||
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('opcache_invalidate'))
|
||||
{
|
||||
@\opcache_invalidate(APP_INDEX_ROOT_PATH.'index.php', true);
|
||||
}
|
||||
|
||||
if (\MailSo\Base\Utils::FunctionExistsAndEnabled('apc_delete_file'))
|
||||
{
|
||||
@\apc_delete_file(APP_INDEX_ROOT_PATH.'index.php');
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Cannot copy new package files', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||
$this->oLogger->Write($sTmpFolder.'/rainloop/ -> '.APP_INDEX_ROOT_PATH.'rainloop/', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!empty($sNewVersion))
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('"'.$sNewVersion.'" version already installed', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($bResult)
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Cannot validate package files', \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||
}
|
||||
}
|
||||
|
||||
\MailSo\Base\Utils::RecRmDir($sTmpFolder);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($this->oLogger)
|
||||
{
|
||||
$this->oLogger->Write('Cannot create tmp folder: '.$sTmpFolder, \MailSo\Log\Enumerations\Type::ERROR, 'INSTALLER');
|
||||
}
|
||||
}
|
||||
|
||||
@\unlink($sTmp);
|
||||
}
|
||||
|
||||
return $bResult;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,252 +1,342 @@
|
|||
|
||||
// mixins +++
|
||||
.thm-linear-gradient-mixin(@start, @end) when (iscolor(@start)) and (iscolor(@end)) {
|
||||
background-color: mix(@start, @end, 60%) !important;
|
||||
background-image: -moz-linear-gradient(top, @start, @end) !important; // FF 3.6+
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start), to(@end)) !important; // Safari 4+, Chrome 2+
|
||||
background-image: -webkit-linear-gradient(top, @start, @end) !important; // Safari 5.1+, Chrome 10+
|
||||
background-image: -o-linear-gradient(top, @start, @end !important); // Opera 11.10
|
||||
background-image: linear-gradient(to bottom, @start, @end) !important; // Standard, IE10
|
||||
background-repeat: repeat-x !important;
|
||||
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start),argb(@end))) !important; // IE9 and down
|
||||
}
|
||||
|
||||
.thm-border-radius(@radius) when (ispixel(@radius)) {
|
||||
-webkit-border-radius: @radius !important;
|
||||
-moz-border-radius: @radius !important;
|
||||
border-radius: @radius !important;
|
||||
}
|
||||
|
||||
.thm-box-shadow(@shadow) {
|
||||
-webkit-box-shadow: @shadow !important;
|
||||
-moz-box-shadow: @shadow !important;
|
||||
box-shadow: @shadow !important;
|
||||
}
|
||||
.thm-body-background-image(@value) when (isstring(@value)) {
|
||||
background-image: url("@{base}@{value}") !important;
|
||||
}
|
||||
.thm-body-background-image(@value) when not (isstring(@value)) {
|
||||
background-image: @value !important;
|
||||
}
|
||||
.thm-rgba-background-color(@simple, @rgba) when (@rgba = false) {
|
||||
background-color: @simple !important;
|
||||
}
|
||||
.thm-rgba-background-color(@simple, @rgba) when not (@rgba = false) {
|
||||
background-color: @simple !important;
|
||||
background-color: @rgba !important;
|
||||
}
|
||||
// --- mixins
|
||||
|
||||
.thm-body {
|
||||
color: @main-color;
|
||||
background-color: @main-background-color;
|
||||
background-size: @main-background-size;
|
||||
.thm-body-background-image(@main-background-image);
|
||||
}
|
||||
|
||||
.thm-loading {
|
||||
color: @loading-color !important;
|
||||
text-shadow: @loading-text-shadow !important;
|
||||
|
||||
.e-spinner .e-bounce {
|
||||
background-color: @loading-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-login-desc .desc {
|
||||
color: @loading-color !important;
|
||||
text-shadow: @loading-text-shadow !important;
|
||||
}
|
||||
|
||||
.thm-login {
|
||||
border: @login-border !important;
|
||||
.thm-rgba-background-color(@login-background-color, @login-rgba-background-color);
|
||||
.thm-linear-gradient-mixin(@login-gradient-start, @login-gradient-end);
|
||||
.thm-border-radius(@login-border-radius);
|
||||
.thm-box-shadow(@login-box-shadow);
|
||||
|
||||
&.submitting-pane.submitting {
|
||||
&:before{
|
||||
background: @spinner-background;
|
||||
.thm-border-radius(@login-border-radius);
|
||||
}
|
||||
&:after{
|
||||
border-top-color: @spinner-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thm-login-text {
|
||||
color: @login-color !important;
|
||||
|
||||
.legend, .e-checkbox-icon, .g-ui-link, .social-button, .language-button {
|
||||
color: @login-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-powered, .thm-mobile-switcher {
|
||||
color: @powered-color;
|
||||
a {
|
||||
color: @powered-color;
|
||||
&:hover {
|
||||
color: lighten(@powered-color, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thm-languages {
|
||||
color: @languages-color;
|
||||
.flag-name {
|
||||
color: @languages-color;
|
||||
border-color: @languages-color;
|
||||
}
|
||||
}
|
||||
|
||||
.g-ui-menu {
|
||||
color: @dropdown-menu-color !important;
|
||||
background-color: @dropdown-menu-background-color !important;
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item > .e-link {
|
||||
color: @dropdown-menu-color !important;
|
||||
background-color: @dropdown-menu-background-color !important;
|
||||
|
||||
> i {
|
||||
color: @dropdown-menu-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item.selected > .e-link {
|
||||
background-color: @dropdown-menu-selected-background-color !important;
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item > .e-link:hover, .g-ui-menu .e-item > .e-link:focus {
|
||||
color: @dropdown-menu-hover-color !important;
|
||||
background-color: @dropdown-menu-hover-background-color !important;
|
||||
|
||||
> i {
|
||||
color: @dropdown-menu-hover-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item.disabled > .e-link, .g-ui-menu .e-item.disabled > .e-link:hover {
|
||||
color: @dropdown-menu-disabled-color !important;
|
||||
background-color: @dropdown-menu-background-color !important;
|
||||
|
||||
> i {
|
||||
color: @dropdown-menu-disabled-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-message-list-top-toolbar, .thm-message-list-bottom-toolbar {
|
||||
.thm-rgba-background-color(@message-list-toolbar-background-color, @message-list-toolbar-rgba-background-color);
|
||||
.thm-linear-gradient-mixin(@message-list-toolbar-gradient-start, @message-list-toolbar-gradient-end);
|
||||
}
|
||||
|
||||
.thm-folders .e-link {
|
||||
|
||||
color: @folders-disabled-color !important;
|
||||
|
||||
&.selectable {
|
||||
color: @folders-color !important;
|
||||
}
|
||||
|
||||
&.selectable:hover {
|
||||
color: @folders-hover-color !important;
|
||||
.thm-rgba-background-color(@folders-hover-background-color, @folders-hover-rgba-background-color);
|
||||
}
|
||||
|
||||
&.selectable.selected {
|
||||
color: @folders-selected-color !important;
|
||||
.thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color);
|
||||
}
|
||||
|
||||
&.focused {
|
||||
color: @folders-focused-color !important;
|
||||
.thm-rgba-background-color(@folders-focused-background-color, @folders-focused-rgba-background-color);
|
||||
}
|
||||
|
||||
&.selectable.droppableHover {
|
||||
color: @folders-drop-color !important;
|
||||
.thm-rgba-background-color(@folders-drop-background-color, @folders-drop-rgba-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.thm-settings-menu .e-item {
|
||||
|
||||
.e-link {
|
||||
color: @settings-menu-disabled-color !important;
|
||||
}
|
||||
|
||||
&.selectable .e-link {
|
||||
color: @settings-menu-color !important;
|
||||
}
|
||||
|
||||
&.selectable:hover .e-link {
|
||||
.thm-rgba-background-color(@settings-menu-hover-background-color, @settings-menu-hover-rgba-background-color);
|
||||
color: @settings-menu-hover-color !important;
|
||||
}
|
||||
|
||||
&.selectable.selected .e-link {
|
||||
.thm-rgba-background-color(@settings-menu-selected-background-color, @settings-menu-selected-rgba-background-color);
|
||||
color: @settings-menu-selected-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-message-view-background-color {
|
||||
.thm-rgba-background-color(@message-background-color, @message-rgba-background-color);
|
||||
}
|
||||
|
||||
#rl-app{
|
||||
display: block;
|
||||
}
|
||||
|
||||
html.no-css {
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, Verdana, Geneva, sans-serif;
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#rl-loading, #rl-loading-error {
|
||||
position: absolute;
|
||||
font-size: 30px;
|
||||
line-height: 130%;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
height: 65px;
|
||||
margin: 0;
|
||||
margin-top: -60px;
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.progressjs-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.thm-body {
|
||||
color: #333;
|
||||
background-color: #aaa;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.thm-loading {
|
||||
color: #333 !important;
|
||||
text-shadow: none !important;
|
||||
|
||||
.e-spinner .e-bounce {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-login-desc .desc {
|
||||
color: #333 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// mixins +++
|
||||
.thm-linear-gradient-mixin(@start, @end) when (iscolor(@start)) and (iscolor(@end)) {
|
||||
background-color: mix(@start, @end, 60%) !important;
|
||||
background-image: -moz-linear-gradient(top, @start, @end) !important; // FF 3.6+
|
||||
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(@start), to(@end)) !important; // Safari 4+, Chrome 2+
|
||||
background-image: -webkit-linear-gradient(top, @start, @end) !important; // Safari 5.1+, Chrome 10+
|
||||
background-image: -o-linear-gradient(top, @start, @end !important); // Opera 11.10
|
||||
background-image: linear-gradient(to bottom, @start, @end) !important; // Standard, IE10
|
||||
background-repeat: repeat-x !important;
|
||||
filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)",argb(@start),argb(@end))) !important; // IE9 and down
|
||||
}
|
||||
|
||||
.thm-border-radius(@radius) when (ispixel(@radius)) {
|
||||
-webkit-border-radius: @radius !important;
|
||||
-moz-border-radius: @radius !important;
|
||||
border-radius: @radius !important;
|
||||
}
|
||||
|
||||
.thm-box-shadow(@shadow) {
|
||||
-webkit-box-shadow: @shadow !important;
|
||||
-moz-box-shadow: @shadow !important;
|
||||
box-shadow: @shadow !important;
|
||||
}
|
||||
.thm-body-background-image(@value) when (isstring(@value)) {
|
||||
background-image: url("@{base}@{value}") !important;
|
||||
}
|
||||
.thm-body-background-image(@value) when not (isstring(@value)) {
|
||||
background-image: @value !important;
|
||||
}
|
||||
.thm-rgba-background-color(@simple, @rgba) when (@rgba = false) {
|
||||
background-color: @simple !important;
|
||||
}
|
||||
.thm-rgba-background-color(@simple, @rgba) when not (@rgba = false) {
|
||||
background-color: @simple !important;
|
||||
background-color: @rgba !important;
|
||||
}
|
||||
// --- mixins
|
||||
|
||||
.thm-body {
|
||||
color: @main-color;
|
||||
background-color: @main-background-color;
|
||||
background-size: @main-background-size;
|
||||
.thm-body-background-image(@main-background-image);
|
||||
}
|
||||
|
||||
.thm-loading {
|
||||
color: @loading-color !important;
|
||||
text-shadow: @loading-text-shadow !important;
|
||||
|
||||
.e-spinner .e-bounce {
|
||||
background-color: @loading-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-login-desc .desc {
|
||||
color: @loading-color !important;
|
||||
text-shadow: @loading-text-shadow !important;
|
||||
}
|
||||
|
||||
.thm-login {
|
||||
border: @login-border !important;
|
||||
.thm-rgba-background-color(@login-background-color, @login-rgba-background-color);
|
||||
.thm-linear-gradient-mixin(@login-gradient-start, @login-gradient-end);
|
||||
.thm-border-radius(@login-border-radius);
|
||||
.thm-box-shadow(@login-box-shadow);
|
||||
|
||||
&.submitting-pane.submitting {
|
||||
&:before{
|
||||
background: @spinner-background;
|
||||
.thm-border-radius(@login-border-radius);
|
||||
}
|
||||
&:after{
|
||||
border-top-color: @spinner-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thm-login-text {
|
||||
color: @login-color !important;
|
||||
|
||||
.legend, .e-checkbox-icon, .g-ui-link, .social-button, .language-button {
|
||||
color: @login-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-powered, .thm-mobile-switcher {
|
||||
color: @powered-color;
|
||||
a {
|
||||
color: @powered-color;
|
||||
&:hover {
|
||||
color: lighten(@powered-color, 20%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thm-languages {
|
||||
color: @languages-color;
|
||||
.flag-name {
|
||||
color: @languages-color;
|
||||
border-color: @languages-color;
|
||||
}
|
||||
}
|
||||
|
||||
.g-ui-menu {
|
||||
color: @dropdown-menu-color !important;
|
||||
background-color: @dropdown-menu-background-color !important;
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item > .e-link {
|
||||
color: @dropdown-menu-color !important;
|
||||
background-color: @dropdown-menu-background-color !important;
|
||||
|
||||
> i {
|
||||
color: @dropdown-menu-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item.selected > .e-link {
|
||||
background-color: @dropdown-menu-selected-background-color !important;
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item > .e-link:hover, .g-ui-menu .e-item > .e-link:focus {
|
||||
color: @dropdown-menu-hover-color !important;
|
||||
background-color: @dropdown-menu-hover-background-color !important;
|
||||
|
||||
> i {
|
||||
color: @dropdown-menu-hover-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.g-ui-menu .e-item.disabled > .e-link, .g-ui-menu .e-item.disabled > .e-link:hover {
|
||||
color: @dropdown-menu-disabled-color !important;
|
||||
background-color: @dropdown-menu-background-color !important;
|
||||
|
||||
> i {
|
||||
color: @dropdown-menu-disabled-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-message-list-top-toolbar, .thm-message-list-bottom-toolbar {
|
||||
.thm-rgba-background-color(@message-list-toolbar-background-color, @message-list-toolbar-rgba-background-color);
|
||||
.thm-linear-gradient-mixin(@message-list-toolbar-gradient-start, @message-list-toolbar-gradient-end);
|
||||
}
|
||||
|
||||
.thm-folders .e-link {
|
||||
|
||||
color: @folders-disabled-color !important;
|
||||
|
||||
&.selectable {
|
||||
color: @folders-color !important;
|
||||
}
|
||||
|
||||
&.selectable:hover {
|
||||
color: @folders-hover-color !important;
|
||||
.thm-rgba-background-color(@folders-hover-background-color, @folders-hover-rgba-background-color);
|
||||
}
|
||||
|
||||
&.selectable.selected {
|
||||
color: @folders-selected-color !important;
|
||||
.thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color);
|
||||
}
|
||||
|
||||
&.focused {
|
||||
color: @folders-focused-color !important;
|
||||
.thm-rgba-background-color(@folders-focused-background-color, @folders-focused-rgba-background-color);
|
||||
}
|
||||
|
||||
&.selectable.droppableHover {
|
||||
color: @folders-drop-color !important;
|
||||
.thm-rgba-background-color(@folders-drop-background-color, @folders-drop-rgba-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.thm-settings-menu .e-item {
|
||||
|
||||
.e-link {
|
||||
color: @settings-menu-disabled-color !important;
|
||||
}
|
||||
|
||||
&.selectable .e-link {
|
||||
color: @settings-menu-color !important;
|
||||
}
|
||||
|
||||
&.selectable:hover .e-link {
|
||||
.thm-rgba-background-color(@settings-menu-hover-background-color, @settings-menu-hover-rgba-background-color);
|
||||
color: @settings-menu-hover-color !important;
|
||||
}
|
||||
|
||||
&.selectable.selected .e-link {
|
||||
.thm-rgba-background-color(@settings-menu-selected-background-color, @settings-menu-selected-rgba-background-color);
|
||||
color: @settings-menu-selected-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-message-view-background-color {
|
||||
.thm-rgba-background-color(@message-background-color, @message-rgba-background-color);
|
||||
}
|
||||
|
||||
#rl-app{
|
||||
display: block;
|
||||
}
|
||||
|
||||
html.no-css {
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Arial, Verdana, Geneva, sans-serif;
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#rl-loading, #rl-loading-error {
|
||||
position: absolute;
|
||||
font-size: 30px;
|
||||
line-height: 130%;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
height: 65px;
|
||||
margin: 0;
|
||||
margin-top: -60px;
|
||||
background-color: transparent;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.progressjs-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.thm-body {
|
||||
color: #333;
|
||||
background-color: #aaa;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.thm-loading {
|
||||
color: #333 !important;
|
||||
text-shadow: none !important;
|
||||
|
||||
.e-spinner .e-bounce {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.thm-login-desc .desc {
|
||||
color: #333 !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// glass style
|
||||
html.glass {
|
||||
|
||||
@glass-color: #fff !important;
|
||||
@glass-p-color: #aaa !important;
|
||||
@glass-m-color: rgba(255, 255, 255, .8) !important;
|
||||
|
||||
.thm-login {
|
||||
border: none !important;
|
||||
background: none !important;
|
||||
background: rgba(0, 0, 0, .3) !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
.controls {
|
||||
.input-append .add-on i {
|
||||
color: @glass-m-color;
|
||||
text-shadow: none !important;
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
input {
|
||||
border: 1px solid none !important;
|
||||
background: none !important;
|
||||
outline: none !important;
|
||||
text-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
color: @glass-color;
|
||||
border-color: @glass-m-color;
|
||||
|
||||
&::-webkit-input-placeholder{
|
||||
color: @glass-color;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
&::-moz-placeholder{
|
||||
color: @glass-color;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
&:-moz-placeholder{
|
||||
color: @glass-color;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
&:-ms-input-placeholder{
|
||||
color: @glass-color;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
&:input-placeholder{
|
||||
color: @glass-color;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
&:placeholder{
|
||||
color: @glass-color;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
&:focus{
|
||||
border-color: @glass-color;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
border: 1px solid none !important;
|
||||
background: none !important;
|
||||
outline: none !important;
|
||||
text-shadow: none !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
color: @glass-color;
|
||||
border-color: @glass-m-color;
|
||||
|
||||
&:hover, &:active{
|
||||
border-color: @glass-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thm-login-text {
|
||||
color: @glass-m-color;
|
||||
text-shadow: none !important;
|
||||
|
||||
.legend, .e-checkbox-icon, .g-ui-link, .social-button, .language-button {
|
||||
color: @glass-m-color;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,47 @@
|
|||
<div class="b-login-content">
|
||||
<div class="loginFormWrapper" data-bind="css: {'afterLoginHide': formHidden}">
|
||||
<center>
|
||||
<div class="alert alertError" data-bind="visible: '' !== submitError()">
|
||||
<button type="button" class="close" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
</div>
|
||||
<div class="wrapper-parent">
|
||||
<form class="wrapper submitting-pane loginForm thm-login thm-login-text" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError, 'submitting': submitRequest()}">
|
||||
<div class="controls" data-bind="css: {'error': loginError, 'animated': loginErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level inputLogin checkAutocomplete"
|
||||
name="RainLoopAdminLogin" id="RainLoopAdminLogin"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_LOGIN"
|
||||
data-bind="textInput: login, hasFocus: loginFocus, disable: submitRequest" />
|
||||
<span class="add-on">
|
||||
<i class="icon-user"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="css: {'error': passwordError, 'animated': passwordErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="password" class="input-block-level inputPassword checkAutocomplete"
|
||||
placeholder="Password" name="RainLoopAdminPassword" id="RainLoopAdminPassword"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_PASSWORD"
|
||||
data-bind="textInput: password, disable: submitRequest" />
|
||||
<span class="add-on">
|
||||
<i class="icon-key"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn btn-large btn-block buttonLogin" data-bind="command: submitCommand">
|
||||
<span data-i18n="LOGIN/BUTTON_LOGIN"></span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="e-powered thm-powered" data-bind="visible: logoPowered">
|
||||
Powered by <a href="http://www.rainloop.net" target="_blank">RainLoop</a>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
<div class="loginAfter"></div>
|
||||
<div class="b-login-content">
|
||||
<div class="loginFormWrapper" data-bind="css: {'afterLoginHide': formHidden}">
|
||||
<center>
|
||||
<div class="alert alertError" data-bind="visible: '' !== submitError()">
|
||||
<button type="button" class="close" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
</div>
|
||||
<div class="wrapper-parent">
|
||||
<form class="wrapper submitting-pane loginForm thm-login thm-login-text" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError, 'submitting': submitRequest()}">
|
||||
<div class="controls" data-bind="css: {'error': loginError, 'animated': loginErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="text" class="input-block-level inputLogin checkAutocomplete"
|
||||
name="RainLoopAdminLogin" id="RainLoopAdminLogin"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_LOGIN"
|
||||
data-bind="textInput: login, hasFocus: loginFocus, disable: submitRequest" />
|
||||
<span class="add-on">
|
||||
<i class="icon-user"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="css: {'error': passwordError, 'animated': passwordErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="password" class="input-block-level inputPassword checkAutocomplete"
|
||||
placeholder="Password" name="RainLoopAdminPassword" id="RainLoopAdminPassword"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false" data-i18n="[placeholder]LOGIN/LABEL_PASSWORD"
|
||||
data-bind="textInput: password, disable: submitRequest" />
|
||||
<span class="add-on">
|
||||
<i class="icon-key"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn btn-large btn-block buttonLogin" data-bind="command: submitCommand">
|
||||
<span data-i18n="LOGIN/BUTTON_LOGIN"></span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="e-powered thm-powered" data-bind="visible: logoPowered">
|
||||
Powered by <a href="http://www.rainloop.net" target="_blank">RainLoop</a>
|
||||
</div>
|
||||
</center>
|
||||
</div>
|
||||
<div class="loginAfter"></div>
|
||||
<div>
|
||||
|
|
@ -1,146 +1,146 @@
|
|||
<div class="b-login-content">
|
||||
<div class="loginFormWrapper" data-bind="css: {'afterLoginHide': formHidden}">
|
||||
<center class="plugin-mark-Login-BeforeLogo">
|
||||
{{INCLUDE/BeforeLogo/PLACE}}
|
||||
<!-- ko if: logoImg -->
|
||||
<div class="logoWrapper plugin-mark-Login-AfterLogo">
|
||||
<img class="logoImg" data-bind="attr: {'src': logoImg }" />
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<div class="descWrapper thm-login-desc plugin-mark-Login-AfterLogoDescription" data-bind="visible: '' !== loginDescription">
|
||||
<span class="desc" data-bind="text: loginDescription"></span>
|
||||
</div>
|
||||
{{INCLUDE/AfterLogo/PLACE}}
|
||||
<div class="alert alertError" data-bind="visible: '' !== submitError()">
|
||||
<button type="button" class="close" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
<div data-bind="visible: '' !== submitErrorAddidional()">
|
||||
<br />
|
||||
<span data-bind="text: submitErrorAddidional"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper-parent">
|
||||
<div class="wrapper loginWelcomeForm thm-login-text" data-bind="css: {'welcome-on': welcome}">
|
||||
<!-- ko template: { name: 'LoginWelcome' } --><!-- /ko -->
|
||||
</div>
|
||||
<form class="wrapper submitting-pane loginForm thm-login thm-login-text" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError, 'welcome-off': welcome, 'submitting': submitRequest()}">
|
||||
{{INCLUDE/TopControlGroup/PLACE}}
|
||||
<div class="controls plugin-mark-Login-TopControlGroup" data-bind="css: {'error': emailError, 'animated': emailErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="email" class="i18n input-block-level inputEmail checkAutocomplete"
|
||||
name="RainLoopEmail" id="RainLoopEmail"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="textInput: email, hasFocus: emailFocus, disable: submitRequest" data-i18n="[placeholder]LOGIN/LABEL_EMAIL" />
|
||||
<span class="add-on">
|
||||
<i class="icon-mail"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="css: {'error': passwordError, 'animated': passwordErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="password" class="i18n input-block-level inputPassword checkAutocomplete"
|
||||
name="RainLoopPassword" id="RainLoopPassword"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="textInput: password, hasFocus: passwordFocus, disable: submitRequest" data-i18n="[placeholder]LOGIN/LABEL_PASSWORD" />
|
||||
<span class="add-on">
|
||||
<i class="icon-key"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="visible: additionalCode.visibility(), css: {'error': additionalCode.error, 'animated': additionalCode.errorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="text" class="i18n input-block-level inputAdditionalCode"
|
||||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
style="padding-right: 35px;"
|
||||
data-bind="textInput: additionalCode, hasFocus: additionalCode.focused, disable: submitRequest" data-i18n="[placeholder]LOGIN/LABEL_VERIFICATION_CODE" />
|
||||
<span class="add-on">
|
||||
<i class="icon-key"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls plugin-mark-Login-BottomControlGroup" data-bind="visible: additionalCode.visibility()">
|
||||
<div class="additionalCodeSignMeLabel" data-bind="component: {
|
||||
name: 'CheckboxSimple',
|
||||
params: {
|
||||
label: 'LOGIN/LABEL_DONT_ASK_VERIFICATION_CODE',
|
||||
value: additionalCodeSignMe
|
||||
}
|
||||
}"></div>
|
||||
</div>
|
||||
{{INCLUDE/BottomControlGroup/PLACE}}
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn btn-large btn-block buttonLogin" data-bind="command: submitCommand, hasFocus: submitFocus">
|
||||
<span class="i18n i18n-animation" data-i18n="LOGIN/BUTTON_SIGN_IN"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="controls clearfix" style="margin-bottom: 20px">
|
||||
<div class="pull-right social-buttons">
|
||||
<a href="#" tabindex="-1" class="social-button" data-bind="visible: facebookLoginEnabled, command: facebookCommand, tooltip: 'LOGIN/TITLE_SIGN_IN_FACEBOOK'">
|
||||
<i class="icon-facebook-alt"></i>
|
||||
</a>
|
||||
<a href="#" tabindex="-1" class="social-button" data-bind="visible: googleLoginEnabled, command: googleCommand, tooltip: 'LOGIN/TITLE_SIGN_IN_GOOGLE'">
|
||||
<i class="icon-google"></i>
|
||||
</a>
|
||||
<a href="#" tabindex="-1" class="social-button" data-bind="visible: twitterLoginEnabled, command: twitterCommand, tooltip: 'LOGIN/TITLE_SIGN_IN_TWITTER'">
|
||||
<i class="icon-twitter"></i>
|
||||
</a>
|
||||
<a href="#" tabindex="-1" class="language-button" data-bind="visible: allowLanguagesOnLogin() && !socialLoginEnabled(), click: selectLanguage, tooltip: 'POPUPS_LANGUAGES/TITLE_LANGUAGES'">
|
||||
<i data-bind="css: langRequest() ? 'icon-spinner animated' : 'icon-world'"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="signMeLabel" data-bind="visible: signMeVisibility, component: {
|
||||
name: 'CheckboxSimple',
|
||||
params: {
|
||||
label: 'LOGIN/LABEL_SIGN_ME',
|
||||
labelAnimated: true,
|
||||
value: signMe
|
||||
}
|
||||
}"></div>
|
||||
|
||||
</div>
|
||||
<div class="controls clearfix" data-bind="visible: '' !== forgotPasswordLinkUrl || '' !== registrationLinkUrl">
|
||||
<div class="forgot-link thm-forgot pull-left" data-bind="visible: '' !== forgotPasswordLinkUrl" style="text-align: center">
|
||||
<a href="#" target="_blank" class="g-ui-link" data-bind="attr: {href: forgotPasswordLinkUrl}, css: {'pull-right': '' !== registrationLinkUrl}"
|
||||
><span class="i18n" data-i18n="LOGIN/LABEL_FORGOT_PASSWORD"></span></a>
|
||||
</div>
|
||||
|
||||
<div class="registration-link thm-registration pull-right" data-bind="visible: '' !== registrationLinkUrl" style="text-align: center">
|
||||
<a href="#" target="_blank" class="g-ui-link" data-bind="attr: {href: registrationLinkUrl}, css: {'pull-left': '' !== forgotPasswordLinkUrl}"
|
||||
><span class="i18n" data-i18n="LOGIN/LABEL_REGISTRATION"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="e-powered thm-powered" data-bind="visible: logoPowered">Powered by <a href="http://www.rainloop.net" target="_blank">RainLoop</a></div>
|
||||
<div class="e-mobile-switcher thm-mobile-switcher">
|
||||
<span data-bind="visible: !mobile && mobileDevice">
|
||||
<i class="icon-mobile"></i>
|
||||
|
||||
<a href="./?/Mobile/" tabindex="-1">
|
||||
<span class="i18n" data-i18n="MOBILE/BUTTON_MOBILE_VERSION"></span>
|
||||
</a>
|
||||
</span>
|
||||
<span data-bind="visible: mobile">
|
||||
<i class="icon-laptop"></i>
|
||||
|
||||
<a href="./?/SkipMobile/" tabindex="-1">
|
||||
<span class="i18n" data-i18n="MOBILE/BUTTON_DESKTOP_VERSION"></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="e-languages thm-languages plugin-mark-Login-BottomFooter" data-bind="visible: allowLanguagesOnLogin() && socialLoginEnabled()">
|
||||
<label class="flag-selector">
|
||||
<i data-bind="css: langRequest() ? 'icon-spinner animated' : 'icon-world'"></i>
|
||||
|
||||
<span class="flag-name" tabindex="0" data-bind="text: languageFullName, click: selectLanguage, onSpace: selectLanguage, onEnter: selectLanguage, onTab: selectLanguageOnTab"></span>
|
||||
</label>
|
||||
</div>
|
||||
{{INCLUDE/BottomFooter/PLACE}}
|
||||
</center>
|
||||
</div>
|
||||
<a href="#" onclick="return false;"></a>
|
||||
<div class="loginAfter"></div>
|
||||
<div class="b-login-content">
|
||||
<div class="loginFormWrapper" data-bind="css: {'afterLoginHide': formHidden}">
|
||||
<center class="plugin-mark-Login-BeforeLogo">
|
||||
{{INCLUDE/BeforeLogo/PLACE}}
|
||||
<!-- ko if: logoImg -->
|
||||
<div class="logoWrapper plugin-mark-Login-AfterLogo">
|
||||
<img class="logoImg" data-bind="attr: {'src': logoImg }" />
|
||||
</div>
|
||||
<!-- /ko -->
|
||||
<div class="descWrapper thm-login-desc plugin-mark-Login-AfterLogoDescription" data-bind="visible: '' !== loginDescription">
|
||||
<span class="desc" data-bind="text: loginDescription"></span>
|
||||
</div>
|
||||
{{INCLUDE/AfterLogo/PLACE}}
|
||||
<div class="alert alertError" data-bind="visibleAnimated: '' !== submitError()">
|
||||
<button type="button" class="close" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
<div data-bind="visible: '' !== submitErrorAddidional()">
|
||||
<br />
|
||||
<span data-bind="text: submitErrorAddidional"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wrapper-parent">
|
||||
<div class="wrapper loginWelcomeForm thm-login-text" data-bind="css: {'welcome-on': welcome}">
|
||||
<!-- ko template: { name: 'LoginWelcome' } --><!-- /ko -->
|
||||
</div>
|
||||
<form class="wrapper submitting-pane loginForm thm-login thm-login-text" action="#/" data-bind="submit: submitForm, css: {'errorAnimated': formError, 'welcome-off': welcome, 'submitting': submitRequest()}">
|
||||
{{INCLUDE/TopControlGroup/PLACE}}
|
||||
<div class="controls plugin-mark-Login-TopControlGroup" data-bind="css: {'error': emailError, 'animated': emailErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="email" class="i18n input-block-level inputEmail checkAutocomplete"
|
||||
name="RainLoopEmail" id="RainLoopEmail"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="textInput: email, hasFocus: emailFocus, disable: submitRequest" data-i18n="[placeholder]LOGIN/LABEL_EMAIL" />
|
||||
<span class="add-on">
|
||||
<i class="icon-mail"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="css: {'error': passwordError, 'animated': passwordErrorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="password" class="i18n input-block-level inputPassword checkAutocomplete"
|
||||
name="RainLoopPassword" id="RainLoopPassword"
|
||||
style="padding-right: 35px;"
|
||||
autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="textInput: password, hasFocus: passwordFocus, disable: submitRequest" data-i18n="[placeholder]LOGIN/LABEL_PASSWORD" />
|
||||
<span class="add-on">
|
||||
<i class="icon-key"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls" data-bind="visible: additionalCode.visibility(), css: {'error': additionalCode.error, 'animated': additionalCode.errorAnimation}">
|
||||
<div class="input-append">
|
||||
<input type="text" class="i18n input-block-level inputAdditionalCode"
|
||||
autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
style="padding-right: 35px;"
|
||||
data-bind="textInput: additionalCode, hasFocus: additionalCode.focused, disable: submitRequest" data-i18n="[placeholder]LOGIN/LABEL_VERIFICATION_CODE" />
|
||||
<span class="add-on">
|
||||
<i class="icon-key"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="controls plugin-mark-Login-BottomControlGroup" data-bind="visible: additionalCode.visibility()">
|
||||
<div class="additionalCodeSignMeLabel" data-bind="component: {
|
||||
name: 'CheckboxSimple',
|
||||
params: {
|
||||
label: 'LOGIN/LABEL_DONT_ASK_VERIFICATION_CODE',
|
||||
value: additionalCodeSignMe
|
||||
}
|
||||
}"></div>
|
||||
</div>
|
||||
{{INCLUDE/BottomControlGroup/PLACE}}
|
||||
<div class="controls">
|
||||
<button type="submit" class="btn btn-large btn-block buttonLogin" data-bind="command: submitCommand, hasFocus: submitFocus">
|
||||
<span class="i18n i18n-animation" data-i18n="LOGIN/BUTTON_SIGN_IN"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="controls clearfix" style="margin-bottom: 20px">
|
||||
<div class="pull-right social-buttons">
|
||||
<a href="#" tabindex="-1" class="social-button" data-bind="visible: facebookLoginEnabled, command: facebookCommand, tooltip: 'LOGIN/TITLE_SIGN_IN_FACEBOOK'">
|
||||
<i class="icon-facebook-alt"></i>
|
||||
</a>
|
||||
<a href="#" tabindex="-1" class="social-button" data-bind="visible: googleLoginEnabled, command: googleCommand, tooltip: 'LOGIN/TITLE_SIGN_IN_GOOGLE'">
|
||||
<i class="icon-google"></i>
|
||||
</a>
|
||||
<a href="#" tabindex="-1" class="social-button" data-bind="visible: twitterLoginEnabled, command: twitterCommand, tooltip: 'LOGIN/TITLE_SIGN_IN_TWITTER'">
|
||||
<i class="icon-twitter"></i>
|
||||
</a>
|
||||
<a href="#" tabindex="-1" class="language-button" data-bind="visible: allowLanguagesOnLogin() && !socialLoginEnabled(), click: selectLanguage, tooltip: 'POPUPS_LANGUAGES/TITLE_LANGUAGES'">
|
||||
<i data-bind="css: langRequest() ? 'icon-spinner animated' : 'icon-world'"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="signMeLabel" data-bind="visible: signMeVisibility, component: {
|
||||
name: 'CheckboxSimple',
|
||||
params: {
|
||||
label: 'LOGIN/LABEL_SIGN_ME',
|
||||
labelAnimated: true,
|
||||
value: signMe
|
||||
}
|
||||
}"></div>
|
||||
|
||||
</div>
|
||||
<div class="controls clearfix" data-bind="visible: '' !== forgotPasswordLinkUrl || '' !== registrationLinkUrl">
|
||||
<div class="forgot-link thm-forgot pull-left" data-bind="visible: '' !== forgotPasswordLinkUrl" style="text-align: center">
|
||||
<a href="#" target="_blank" class="g-ui-link" data-bind="attr: {href: forgotPasswordLinkUrl}, css: {'pull-right': '' !== registrationLinkUrl}"
|
||||
><span class="i18n" data-i18n="LOGIN/LABEL_FORGOT_PASSWORD"></span></a>
|
||||
</div>
|
||||
|
||||
<div class="registration-link thm-registration pull-right" data-bind="visible: '' !== registrationLinkUrl" style="text-align: center">
|
||||
<a href="#" target="_blank" class="g-ui-link" data-bind="attr: {href: registrationLinkUrl}, css: {'pull-left': '' !== forgotPasswordLinkUrl}"
|
||||
><span class="i18n" data-i18n="LOGIN/LABEL_REGISTRATION"></span></a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="e-powered thm-powered" data-bind="visible: logoPowered">Powered by <a href="http://www.rainloop.net" target="_blank">RainLoop</a></div>
|
||||
<div class="e-mobile-switcher thm-mobile-switcher">
|
||||
<span data-bind="visible: !mobile && mobileDevice">
|
||||
<i class="icon-mobile"></i>
|
||||
|
||||
<a href="./?/Mobile/" tabindex="-1">
|
||||
<span class="i18n" data-i18n="MOBILE/BUTTON_MOBILE_VERSION"></span>
|
||||
</a>
|
||||
</span>
|
||||
<span data-bind="visible: mobile">
|
||||
<i class="icon-laptop"></i>
|
||||
|
||||
<a href="./?/SkipMobile/" tabindex="-1">
|
||||
<span class="i18n" data-i18n="MOBILE/BUTTON_DESKTOP_VERSION"></span>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="e-languages thm-languages plugin-mark-Login-BottomFooter" data-bind="visible: allowLanguagesOnLogin() && socialLoginEnabled()">
|
||||
<label class="flag-selector">
|
||||
<i data-bind="css: langRequest() ? 'icon-spinner animated' : 'icon-world'"></i>
|
||||
|
||||
<span class="flag-name" tabindex="0" data-bind="text: languageFullName, click: selectLanguage, onSpace: selectLanguage, onEnter: selectLanguage, onTab: selectLanguageOnTab"></span>
|
||||
</label>
|
||||
</div>
|
||||
{{INCLUDE/BottomFooter/PLACE}}
|
||||
</center>
|
||||
</div>
|
||||
<a href="#" onclick="return false;"></a>
|
||||
<div class="loginAfter"></div>
|
||||
</div>
|
||||
|
|
@ -1,38 +1,38 @@
|
|||
<div class="b-folders g-ui-user-select-none thm-folders" data-bind="css: {'focused': folderListFocused, 'single-root-inbox': foldersListWithSingleInboxRootFolder, 'inbox-is-starred': isInboxStarred}">
|
||||
<div class="b-toolbar btn-toolbar hide-on-mobile">
|
||||
<a class="btn buttonCompose pull-left" data-tooltip-join="top" data-bind="visible: allowComposer, click: composeClick, tooltip: 'FOLDER_LIST/BUTTON_NEW_MESSAGE', css: {'btn-warning': composeInEdit, 'btn-success': !composeInEdit()}">
|
||||
<i class="icon-paper-plane"></i>
|
||||
<span class="btn-text-wrp buttonComposeText">
|
||||
<span class="i18n" data-i18n="FOLDER_LIST/BUTTON_NEW_MESSAGE"></span>
|
||||
</span>
|
||||
</a>
|
||||
<a class="btn buttonContacts pull-left" data-tooltip-join="top" data-bind="visible: allowContacts, click: contactsClick, tooltip: 'FOLDER_LIST/BUTTON_CONTACTS'">
|
||||
<i class="icon-address-book"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="b-content opacity-on-panel-disabled" data-bind="visible: allowFolders, nano: true, scrollerShadows: true, css: {'inbox-is-starred': isInboxStarred}">
|
||||
<div class="content g-scrollbox" data-scroller-shadows-content>
|
||||
<div class="content-wrapper">
|
||||
<div class="b-folders-system" data-bind="template: { name: 'MailFolderListSystemItem', foreach: folderListSystem }"></div>
|
||||
<hr class="b-list-delimiter" />
|
||||
<div class="b-folders-user" data-bind="template: { name: 'MailFolderListItem', foreach: folderList }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="b-content show-on-panel-disabled" data-bind="click: function () { leftPanelDisabled(false); }"></div>
|
||||
<div class="b-footer btn-toolbar hide-on-mobile" data-bind="visible: allowFolders">
|
||||
<div class="btn-group">
|
||||
<a class="btn single buttonResize" data-bind="click: function () { leftPanelDisabled(!leftPanelDisabled()); }">
|
||||
<i data-bind="css: {'icon-resize-out': leftPanelDisabled(), 'icon-resize-in': !leftPanelDisabled()}"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group hide-on-panel-disabled">
|
||||
<a class="btn first" data-bind="click: createFolder">
|
||||
<i data-bind="css: {'icon-folder-add': !foldersChanging(), 'icon-spinner animated': foldersChanging()}"></i>
|
||||
</a>
|
||||
<a class="btn last" data-bind="click: configureFolders">
|
||||
<i class="icon-cog"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="b-folders g-ui-user-select-none thm-folders" data-bind="css: {'focused': folderListFocused, 'single-root-inbox': foldersListWithSingleInboxRootFolder, 'inbox-is-starred': isInboxStarred}">
|
||||
<div class="b-toolbar btn-toolbar hide-on-mobile">
|
||||
<a class="btn buttonCompose pull-left" data-tooltip-join="top" data-bind="visible: allowComposer, click: composeClick, tooltip: 'FOLDER_LIST/BUTTON_NEW_MESSAGE', css: {'btn-warning': composeInEdit, 'btn-success': !composeInEdit()}">
|
||||
<i class="icon-paper-plane"></i>
|
||||
<span class="btn-text-wrp buttonComposeText">
|
||||
<span class="i18n" data-i18n="FOLDER_LIST/BUTTON_NEW_MESSAGE"></span>
|
||||
</span>
|
||||
</a>
|
||||
<a class="btn buttonContacts pull-left" data-tooltip-join="top" data-bind="visible: allowContacts, click: contactsClick, tooltip: 'FOLDER_LIST/BUTTON_CONTACTS'">
|
||||
<i class="icon-address-book"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="b-content opacity-on-panel-disabled" data-bind="visible: allowFolders, nano: true, scrollerShadows: true, css: {'inbox-is-starred': isInboxStarred}">
|
||||
<div class="content g-scrollbox" data-scroller-shadows-content>
|
||||
<div class="content-wrapper">
|
||||
<div class="b-folders-system" data-bind="template: { name: 'MailFolderListSystemItem', foreach: folderListSystem }"></div>
|
||||
<hr class="b-list-delimiter" />
|
||||
<div class="b-folders-user" data-bind="template: { name: 'MailFolderListItem', foreach: folderList }"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="b-content show-on-panel-disabled" data-bind="click: function () { leftPanelDisabled(false); }"></div>
|
||||
<div class="b-footer btn-toolbar hide-on-mobile" data-bind="visible: allowFolders">
|
||||
<div class="btn-group">
|
||||
<a class="btn single buttonResize" data-bind="click: function () { leftPanelDisabled(!leftPanelDisabled()); }">
|
||||
<i data-bind="css: {'icon-resize-out': leftPanelDisabled(), 'icon-resize-in': !leftPanelDisabled()}"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="btn-group hide-on-panel-disabled">
|
||||
<a class="btn first" data-bind="click: createFolder">
|
||||
<i data-bind="css: {'icon-folder-add': !foldersChanging(), 'icon-spinner animated': foldersChanging()}"></i>
|
||||
</a>
|
||||
<a class="btn last" data-bind="click: configureFolders">
|
||||
<i class="icon-cog"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,50 +1,50 @@
|
|||
<div class="popups">
|
||||
<div class="modal hide b-account-add-content g-ui-user-select-none" data-bind="modal: modalVisibility">
|
||||
<div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="command: cancelCommand">×</button>
|
||||
<h3>
|
||||
<span data-bind="visible: isNew" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/TITLE_ADD_ACCOUNT"></span>
|
||||
<span data-bind="visible: !isNew()" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/TITLE_UPDATE_ACCOUNT"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-horizontal">
|
||||
<div class="alert" data-bind="visible: '' !== submitError()">
|
||||
<button type="button" class="close-custom" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
<div data-bind="visible: submitErrorAdditional">
|
||||
<br />
|
||||
<span data-bind="text: submitErrorAdditional"></span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="control-group" data-bind="css: {'error': emailError}">
|
||||
<label class="i18n control-label" data-i18n="LOGIN/LABEL_EMAIL"></label>
|
||||
<div class="controls">
|
||||
<label style="margin-top: 5px;" data-bind="visible: !isNew()"><strong data-bind="text: email"></strong></label>
|
||||
<input type="email" class="inputEmail input-large" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="visible: isNew, textInput: email, onEnter: addAccountCommand, hasfocus: emailFocus" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="css: {'error': passwordError}">
|
||||
<label class="i18n control-label" data-i18n="LOGIN/LABEL_PASSWORD"></label>
|
||||
<div class="controls">
|
||||
<input type="password" class="inputPassword input-large" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="value: password, onEnter: addAccountCommand" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn buttonAddAccount" data-bind="command: addAccountCommand">
|
||||
<i data-bind="visible: isNew, css: {'icon-user-add': !submitRequest(), 'icon-spinner animated': submitRequest()}"></i>
|
||||
<i data-bind="visible: !isNew(), css: {'icon-ok': !submitRequest(), 'icon-spinner animated': submitRequest()}"></i>
|
||||
|
||||
<span data-bind="visible: isNew" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/BUTTON_ADD_ACCOUNT"></span>
|
||||
<span data-bind="visible: !isNew()" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/BUTTON_UPDATE_ACCOUNT"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popups">
|
||||
<div class="modal hide b-account-add-content g-ui-user-select-none" data-bind="modal: modalVisibility">
|
||||
<div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="command: cancelCommand">×</button>
|
||||
<h3>
|
||||
<span data-bind="visible: isNew" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/TITLE_ADD_ACCOUNT"></span>
|
||||
<span data-bind="visible: !isNew()" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/TITLE_UPDATE_ACCOUNT"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-horizontal">
|
||||
<div class="alert" data-bind="visible: '' !== submitError()">
|
||||
<button type="button" class="close-custom" data-bind="click: function () { submitError('') }">×</button>
|
||||
<span data-bind="text: submitError"></span>
|
||||
<div data-bind="visible: submitErrorAdditional">
|
||||
<br />
|
||||
<span data-bind="text: submitErrorAdditional"></span>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="control-group" data-bind="css: {'error': emailError}">
|
||||
<label class="i18n control-label" data-i18n="LOGIN/LABEL_EMAIL"></label>
|
||||
<div class="controls">
|
||||
<label style="margin-top: 5px;" data-bind="visible: !isNew()"><strong data-bind="text: email"></strong></label>
|
||||
<input type="email" class="inputEmail input-large" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="visible: isNew, textInput: email, onEnter: addAccountCommand, hasfocus: emailFocus" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" data-bind="css: {'error': passwordError}">
|
||||
<label class="i18n control-label" data-i18n="LOGIN/LABEL_PASSWORD"></label>
|
||||
<div class="controls">
|
||||
<input type="password" class="inputPassword input-xlarge" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||
data-bind="value: password, onEnter: addAccountCommand" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn buttonAddAccount" data-bind="command: addAccountCommand">
|
||||
<i data-bind="visible: isNew, css: {'icon-user-add': !submitRequest(), 'icon-spinner animated': submitRequest()}"></i>
|
||||
<i data-bind="visible: !isNew(), css: {'icon-ok': !submitRequest(), 'icon-spinner animated': submitRequest()}"></i>
|
||||
|
||||
<span data-bind="visible: isNew" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/BUTTON_ADD_ACCOUNT"></span>
|
||||
<span data-bind="visible: !isNew()" class="i18n" data-i18n="POPUPS_ADD_ACCOUNT/BUTTON_UPDATE_ACCOUNT"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,26 +1,27 @@
|
|||
<div class="popups">
|
||||
<div class="modal hide b-open-pgp-key-add-content g-ui-user-select-none" data-bind="modal: modalVisibility">
|
||||
<div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="command: cancelCommand">×</button>
|
||||
<h3>
|
||||
<span class="i18n" data-i18n="POPUPS_IMPORT_OPEN_PGP_KEY/TITLE_IMPORT_OPEN_PGP_KEY"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-horizontal">
|
||||
<div class="control-group">
|
||||
<textarea class="inputKey input-xxlarge" rows="14" autocomplete="off" data-bind="value: key, hasfocus: key.focus"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn buttonAddAccount" data-bind="command: addOpenPgpKeyCommand">
|
||||
<i class="icon-list-add"></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_IMPORT_OPEN_PGP_KEY/BUTTON_IMPORT_OPEN_PGP_KEY"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popups">
|
||||
<div class="modal hide b-open-pgp-key-add-content g-ui-user-select-none" data-bind="modal: modalVisibility">
|
||||
<div>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-bind="command: cancelCommand">×</button>
|
||||
<h3>
|
||||
<span class="i18n" data-i18n="POPUPS_IMPORT_OPEN_PGP_KEY/TITLE_IMPORT_OPEN_PGP_KEY"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert" data-bind="visible: key.error() && key.errorMessage(), text: key.errorMessage"></div>
|
||||
<div class="form-horizontal">
|
||||
<div class="control-group" data-bind="css: {'error': key.error}">
|
||||
<textarea class="inputKey input-xxlarge" rows="14" autocomplete="off" data-bind="value: key, hasfocus: key.focus"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="btn buttonAddAccount" data-bind="command: addOpenPgpKeyCommand">
|
||||
<i class="icon-list-add"></i>
|
||||
|
||||
<span class="i18n" data-i18n="POPUPS_IMPORT_OPEN_PGP_KEY/BUTTON_IMPORT_OPEN_PGP_KEY"></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
0
rainloop/v/0.0.0/static/js/min/.empty
Normal file
0
rainloop/v/0.0.0/static/js/min/.empty
Normal file
Loading…
Add table
Add a link
Reference in a new issue