%PDF- %PDF-
| Direktori : /www/varak.net/mail2.varak.net_old/libraries/afterlogic/common/managers/sieve/ |
| Current File : /www/varak.net/mail2.varak.net_old/libraries/afterlogic/common/managers/sieve/manager.php |
<?php
/*
* Copyright 2004-2014, AfterLogic Corp.
* Licensed under AGPLv3 license or AfterLogic license
* if commercial version of the product was purchased.
* See the LICENSE file for a full license statement.
*/
/**
* @package Sieve
*/
class CApiSieveManager extends AApiManager
{
/**
* @var bool
*/
static $AutoSave = true;
/**
* @var CApiSieveProtocol
*/
protected $oSieve;
/**
* @var string
*/
protected $sSieveFileName;
/**
* @var array
*/
protected $aSectionsData;
/**
* @var array
*/
protected $aSectionsOrders;
/**
* @var array
*/
protected $aSieves;
/**
* @var string
*/
protected $sGeneralPassword;
/**
* @param CApiGlobalManager &$oManager
*/
public function __construct(CApiGlobalManager &$oManager, $sForcedStorage = '')
{
parent::__construct('sieve', $oManager);
CApi::Inc('common.net.protocols.sieve');
$this->inc('classes.enum');
$this->inc('classes.filter');
$this->aSieves = array();
$this->sGeneralPassword = '';
$this->sSieveFileName = CApi::GetConf('sieve.config.file', 'sieve');
$this->sSieveFolderCharset = CApi::GetConf('sieve.config.filters-folder-charset', 'utf-8');
$this->bSectionsParsed = false;
$this->aSectionsData = array();
$this->aSectionsOrders = array(
'forward',
'autoresponder',
'filters'
);
}
/**
* @param string $sValue
* @return string
*/
private function quoteValue($sValue)
{
return str_replace('"', '\\"', trim($sValue));
}
/**
* @param CAccount $oAccount
* @return array
*/
public function GetAutoresponder($oAccount)
{
$this->parseSectionsData($oAccount);
$sData = $this->getSectionData('autoresponder');
$bEnabled = false;
$sSubject = '';
$sText = '';
$aMatch = array();
if (!empty($sData) && preg_match('/#data=([\d])~([^\n]+)/', $sData, $aMatch) && isset($aMatch[1]) && isset($aMatch[2]))
{
$bEnabled = '1' === (string) $aMatch[1];
$aParts = explode("\x0", base64_decode($aMatch[2]), 2);
if (is_array($aParts) && 2 === count($aParts))
{
$sSubject = $aParts[0];
$sText = $aParts[1];
}
}
return array(
'enabled' => $bEnabled,
'subject' => $sSubject,
'body' => $sText
);
}
/**
* @param CAccount $oAccount
* @param string $sSubject
* @param string $sText
* @param bool $bEnabled
* @return bool
*/
public function SetAutoresponder($oAccount, $sSubject, $sText, $bEnabled = true)
{
$sSubject = str_replace(array("\r", "\n", "\t"), ' ', trim($sSubject));
$sText = str_replace(array("\r"), '', trim($sText));
$sData = '#data='.($bEnabled ? '1' : '0').'~'.base64_encode($sSubject."\x0".$sText)."\n";
$sScriptText = 'vacation :days 1 :subject "'.$this->quoteValue($sSubject).'" "'.$this->quoteValue($sText).'";';
if ($bEnabled)
{
$sData .= $sScriptText;
}
else
{
$sData .= '#'.implode("\n#", explode("\n", $sScriptText));
}
$this->parseSectionsData($oAccount);
$this->setSectionData('autoresponder', $sData);
if (CApiSieveManager::$AutoSave)
{
return $this->resaveSectionsData($oAccount);
}
return true;
}
/**
* @param CAccount $oAccount
* @param string $sText
* @param string $sSubject
* @param bool $bEnabled
* @return bool
*/
public function DisableAutoresponder($oAccount)
{
$aData = $this->GetAutoresponder($oAccount);
$sText = '';
$sSubject = '';
if ($aData && isset($aData[1], $aData[2]))
{
$sText = $aData[2];
$sSubject = $aData[1];
}
return $this->SetAutoresponder($oAccount, $sText, $sSubject, false);
}
/**
* @param CAccount $oAccount
* @return array | false
*/
public function GetForward($oAccount)
{
$this->parseSectionsData($oAccount);
$sData = $this->getSectionData('forward');
$bEnabled = false;
$sForward = '';
$aMatch = array();
if (!empty($sData) && preg_match('/#data=([\d])~([^\n]+)/', $sData, $aMatch) && isset($aMatch[1]) && isset($aMatch[2]))
{
$bEnabled = '1' === (string) $aMatch[1];
$sForward = base64_decode($aMatch[2]);
}
return array(
'enabled' => $bEnabled,
'email' => $sForward
);
}
/**
* @param CAccount $oAccount
* @param string $sForward
* @param bool $bEnabled = true
* @return bool
*/
public function SetForward($oAccount, $sForward, $bEnabled = true)
{
$sData =
'#data='.($bEnabled ? '1' : '0').'~'.base64_encode($sForward)."\n".
($bEnabled ? '' : '#').'redirect :copy "'.$this->quoteValue($sForward).'";'."\n";
$this->parseSectionsData($oAccount);
$this->setSectionData('forward', $sData);
if (CApiSieveManager::$AutoSave)
{
return $this->resaveSectionsData($oAccount);
}
return true;
}
/**
* @param CAcount $oAccount
*
* @return array|false
*/
public function GetSieveFilters($oAccount)
{
$mResult = false;
$sScript = $this->GetFiltersRawData($oAccount);
if (false !== $sScript)
{
$mResult = array();
$aFilters = explode("\n", $sScript);
foreach ($aFilters as $sFilter)
{
$sPattern = '#sieve_filter:';
if (strpos($sFilter, $sPattern) !== false)
{
$sFilter = substr($sFilter, strlen($sPattern));
$aFilter = explode(";", $sFilter);
if (is_array($aFilter) && 5 < count($aFilter))
{
$oFilter = new CFilter($oAccount);
$oFilter->Enable = (bool) trim($aFilter[0]);
$oFilter->Field = (int) trim($aFilter[2]);
$oFilter->Condition = (int) trim($aFilter[1]);
$oFilter->Action = (int) trim($aFilter[4]);
$oFilter->Filter = (string) trim($aFilter[3]);
if (EFilterAction::MoveToFolder === $oFilter->Action && isset($aFilter[5]))
{
$oFilter->FolderFullName = api_Utils::ConvertEncoding($aFilter[5],
$this->sSieveFolderCharset, 'utf7-imap');
}
$mResult[] = $oFilter;
}
unset($oFilter);
}
}
}
return $mResult;
}
/**
* @param CAcount $oAccount
* @param array $aFilters
*
* @return bool
*/
public function UpdateSieveFilters($oAccount, $aFilters)
{
$sFilters = "#sieve filter\n\n";
if ($oAccount)
{
foreach ($aFilters as /* @var $oFilter CFilter */ $oFilter)
{
if ('' === trim($oFilter->Filter))
{
continue;
}
if (EFilterAction::MoveToFolder === $oFilter->Action && '' === trim($oFilter->FolderFullName))
{
continue;
}
$aFields = array();
switch($oFilter->Field)
{
default :
case EFilterFiels::From:
$aFields[] = 'From';
break;
case EFilterFiels::To:
$aFields[] = 'To';
$aFields[] = 'CC';
break;
case EFilterFiels::Subject:
$aFields[] = 'Subject';
break;
}
// condition
foreach ($aFields as $iIndex => $sField)
{
$aFields[$iIndex] = '"'.$this->quoteValue($sField).'"';
}
$sCondition = '';
$sFields = implode(',', $aFields);
switch ($oFilter->Condition)
{
case EFilterCondition::ContainSubstring:
$sCondition = 'if header :contains ['.$sFields.'] "'.$this->quoteValue($oFilter->Filter).'" {';
break;
case EFilterCondition::ContainExactPhrase:
$sCondition = 'if header :is ['.$sFields.'] "'.$this->quoteValue($oFilter->Filter).'" {';
break;
case EFilterCondition::NotContainSubstring:
$sCondition = 'if not header :contains ['.$sFields.'] "'.$this->quoteValue($oFilter->Filter).'" {';
break;
}
// folder
$sFolderFullName = '';
if (EFilterAction::MoveToFolder === $oFilter->Action)
{
$sFolderFullName = api_Utils::ConvertEncoding($oFilter->FolderFullName,
'utf7-imap', $this->sSieveFolderCharset);
}
// action
$sAction = '';
switch($oFilter->Action)
{
case EFilterAction::DeleteFromServerImmediately:
$sAction = 'discard ;';
$sAction .= 'stop ;';
break;
case EFilterAction::MoveToFolder:
$sAction = 'fileinto "'.$this->quoteValue($sFolderFullName).'" ;'."\n";
$sAction .= 'stop ;';
break;
}
$sEnd = '}';
if (!$oFilter->Enable)
{
$sCondition = '#'.$sCondition;
$sAction = '#'.$sAction;
$sEnd = '#'.$sEnd;
}
$sFilters .= "\n".'#sieve_filter:'.implode(';', array(
$oFilter->Enable ? '1' : '0', $oFilter->Condition, $oFilter->Field,
$oFilter->Filter, $oFilter->Action, $sFolderFullName))."\n";
$sFilters .= $sCondition."\n";
$sFilters .= $sAction."\n";
$sFilters .= $sEnd."\n";
}
$sFilters = $sFilters."\n".'#end sieve filter'."\n";
return $this->SetFiltersRawData($oAccount, $sFilters);
}
return false;
}
/**
* @param CAccount $oAccount
* @param string $sForward
* @param bool $bEnabled = true
* @return bool
*/
public function DisableForward($oAccount)
{
$sForward = '';
$aData = $this->GetForward($oAccount);
if ($aData && isset($aData[1]))
{
$sForward = $aData[1];
}
return $this->SetForward($oAccount, $sForward, false);
}
/**
* @param CAccount $oAccount
* @param string $sSectionName = ''
* @param string $sSectionData = ''
* @return bool
*/
public function Resave($oAccount, $sSectionName = '', $sSectionData = '')
{
$this->parseSectionsData($oAccount);
if (!empty($sSectionName) && !empty($sSectionData))
{
$this->setSectionData($sSectionName, $sSectionData);
}
return $this->resaveSectionsData($oAccount);
}
/**
* @param CAccount $oAccount
* @return string
*/
public function GetFiltersRawData($oAccount)
{
$this->parseSectionsData($oAccount);
return $this->getSectionData('filters');
}
/**
* @param CAccount $oAccount
* @param string $sFiltersRawData
* @return bool
*/
public function SetFiltersRawData($oAccount, $sFiltersRawData)
{
$this->parseSectionsData($oAccount);
$this->setSectionData('filters', $sFiltersRawData);
if (CApiSieveManager::$AutoSave)
{
return $this->resaveSectionsData($oAccount);
}
return true;
}
/**
* @param CAccount $oAccount
* @return \MailSo\Sieve\ManageSieveClient | false
*/
protected function getSieveDriver(CAccount $oAccount)
{
$oSieve = false;
if ($oAccount instanceof CAccount)
{
if (!isset($this->aSieves[$oAccount->Email]))
{
$oSieve = \MailSo\Sieve\ManageSieveClient::NewInstance();
$oSieve->SetLogger(\CApi::MailSoLogger());
$this->aSieves[$oAccount->Email] = $oSieve;
}
else
{
$oSieve = $this->aSieves[$oAccount->Email];
}
}
return $oSieve;
}
/**
* @param CAccount $oAccount
* @return \MailSo\Sieve\ManageSieveClient | false
*/
protected function connectSieve($oAccount)
{
$bResult = false;
$oSieve = $this->getSieveDriver($oAccount);
if ($oSieve)
{
if (!$oSieve->IsConnected())
{
$sGeneralHost = CApi::GetConf('sieve.config.host', '');
$sGeneralPassword = CApi::GetConf('sieve.config.general-password', '');
$bResult = $oSieve
->Connect($oAccount->IsInternal || 0 === strlen($sGeneralHost) ? $oAccount->IncomingMailServer : $sGeneralHost, (int) CApi::GetConf('sieve.config.port', 2000), \MailSo\Net\Enumerations\ConnectionSecurityType::NONE)
->Login($oAccount->IncomingMailLogin, 0 === strlen($sGeneralPassword) ? $oAccount->IncomingMailPassword : $sGeneralPassword)
;
}
else
{
$bResult = true;
}
if ($oSieve)
{
return $oSieve;
}
}
return $bResult;
}
/**
* @param CAccount $oAccount
* @return string | false
*/
protected function getSieveFile($oAccount)
{
$sResult = false;
try
{
$oSieve = $this->connectSieve($oAccount);
if ($oSieve)
{
if ($oSieve->IsActiveScript($this->sSieveFileName))
{
$sResult = $oSieve->GetScript($this->sSieveFileName);
}
}
}
catch (\Exception $oException)
{
$sResult = false;
}
return is_string($sResult) ? str_replace("\r", '', $sResult) : false;
}
/**
* @param CAccount $oAccount
* @param string $sText
* @return bool
*/
protected function setSieveFile($oAccount, $sText)
{
$sText = str_replace("\r", '', $sText);
try
{
$oSieve = $this->connectSieve($oAccount);
if ($oSieve)
{
$oSieve->CheckScript($sText);
$oSieve->PutScript($this->sSieveFileName, $sText);
$oSieve->SetActiveScript($this->sSieveFileName);
$bResult = true;
}
}
catch (\Exception $oException)
{
$bResult = false;
}
return $bResult;
}
/**
* @param CAccount $oAccount
* @return bool
*/
protected function resaveSectionsData($oAccount)
{
$this->bSectionsParsed = false;
return $this->setSieveFile($oAccount, $this->selectionsDataToString());
}
/**
* @param CAccount $oAccount
* @param bool $bForced = false
*/
protected function parseSectionsData($oAccount, $bForced = false)
{
if (!$this->bSectionsParsed || $bForced)
{
$sText = $this->getSieveFile($oAccount);
if (false !== $sText)
{
if (is_array($this->aSectionsOrders))
{
foreach ($this->aSectionsOrders as $sSectionName)
{
$aParams = $this->getSectionParams($sSectionName, $sText);
if ($aParams)
{
$this->aSectionsData[$sSectionName] = trim(substr($sText,
$aParams[0] + strlen($aParams[2]),
$aParams[1] - $aParams[0] - strlen($aParams[2])
));
}
}
}
}
}
}
/**
* @return string
*/
protected function selectionsDataToString()
{
$sResult = '';
if (is_array($this->aSectionsOrders))
{
foreach ($this->aSectionsOrders as $sSectionName)
{
if (!empty($this->aSectionsData[$sSectionName]))
{
$sResult .= "\n".
$this->getComment($sSectionName, true)."\n".
$this->aSectionsData[$sSectionName]."\n".
$this->getComment($sSectionName, false)."\n";
};
}
}
$sResult = 'require ["fileinto", "copy", "vacation"] ;'."\n".$sResult;
$sResult = "# Sieve filter\n".$sResult;
$sResult .= "keep ;\n";
return $sResult;
}
/**
* @param string $sSectionName
* @return string
*/
protected function getSectionData($sSectionName)
{
if (in_array($sSectionName, $this->aSectionsOrders) && !empty($this->aSectionsData[$sSectionName]))
{
return $this->aSectionsData[$sSectionName];
}
return '';
}
/**
* @param string $sSectionName
* @param string $sData
*/
protected function setSectionData($sSectionName, $sData)
{
if (in_array($sSectionName, $this->aSectionsOrders))
{
$this->aSectionsData[$sSectionName] = $sData;
}
}
protected function getComment($sSectionName, $bIsBeginComment = true)
{
return '#'.($bIsBeginComment ? 'begin' : 'end').' = '.$sSectionName.' =';
}
protected function getSectionParams($sSectionName, $sText)
{
$aResult = false;
if (!empty($sText))
{
$sBeginComment = $this->getComment($sSectionName, true);
$sEndComment = $this->getComment($sSectionName, false);
$iBegin = strpos($sText, $sBeginComment);
if (false !== $iBegin)
{
$iEnd = strpos($sText, $sEndComment, $iBegin);
if (false !== $iEnd)
{
$aResult = array($iBegin, $iEnd, $sBeginComment, $sEndComment);
}
}
}
return $aResult;
}
}