Find links in html messages

This commit is contained in:
RainLoop Team 2014-02-06 15:56:55 +04:00 committed by RayMan
parent d50c068a3d
commit 041bd1ae1b
6 changed files with 388 additions and 335 deletions

View file

@ -8,6 +8,8 @@ namespace MailSo\Base;
*/ */
class HtmlUtils class HtmlUtils
{ {
static $KOS = '@@_KOS_@@';
/** /**
* @access private * @access private
*/ */
@ -261,14 +263,106 @@ class HtmlUtils
return \implode(';', $aOutStyles); return \implode(';', $aOutStyles);
} }
/**
* @param \DOMDocument $oDom
*/
public static function FindLinksInDOM(&$oDom)
{
$aNodes = $oDom->getElementsByTagName('*');
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{
$sTagNameLower = \strtolower($oElement->tagName);
$sParentTagNameLower = isset($oElement->parentNode) && isset($oElement->parentNode->tagName) ?
\strtolower($oElement->parentNode->tagName) : '';
if (!\in_array($sTagNameLower, array('html', 'meta', 'head', 'style', 'script', 'img', 'button', 'input', 'textarea', 'a')) &&
'a' !== $sParentTagNameLower && $oElement->childNodes && 0 < $oElement->childNodes->length)
{
$oSubItem = null;
$aTextNodes = array();
$iIndex = $oElement->childNodes->length - 1;
while ($iIndex > -1)
{
$oSubItem = $oElement->childNodes->item($iIndex);
if ($oSubItem && XML_TEXT_NODE === $oSubItem->nodeType)
{
$aTextNodes[] = $oSubItem;
}
$iIndex--;
}
unset($oSubItem);
foreach ($aTextNodes as $oTextNode)
{
if ($oTextNode && 0 < \strlen($oTextNode->wholeText)/* && \preg_match('/http[s]?:\/\//i', $oTextNode->wholeText)*/)
{
$sText = \MailSo\Base\LinkFinder::NewInstance()
->Text($oTextNode->wholeText)
->UseDefaultWrappers(true)
->CompileText()
;
$oSubDom = \MailSo\Base\HtmlUtils::GetDomFromText('<html><body>'.$sText.'</body></html>');
if ($oSubDom)
{
$oBodyNodes = $oSubDom->getElementsByTagName('body');
if ($oBodyNodes && 0 < $oBodyNodes->length)
{
$oBodyChildNodes = $oBodyNodes->item(0)->childNodes;
if ($oBodyChildNodes && $oBodyChildNodes->length)
{
for ($iIndex = 0, $iLen = $oBodyChildNodes->length; $iIndex < $iLen; $iIndex++)
{
$oSubItem = $oBodyChildNodes->item($iIndex);
if ($oSubItem)
{
if (XML_ELEMENT_NODE === $oSubItem->nodeType &&
'a' === \strtolower($oSubItem->tagName))
{
$oLink = $oDom->createElement('a',
\str_replace(':', \MailSo\Base\HtmlUtils::$KOS, \htmlspecialchars($oSubItem->nodeValue)));
$sHref = $oSubItem->getAttribute('href');
if ($sHref)
{
$oLink->setAttribute('href', $sHref);
}
$oElement->insertBefore($oLink, $oTextNode);
}
else
{
$oElement->insertBefore($oDom->importNode($oSubItem), $oTextNode);
}
}
}
$oElement->removeChild($oTextNode);
}
}
unset($oBodyNodes);
}
unset($oSubDom, $sText);
}
}
}
}
unset($aNodes);
}
/** /**
* @param string $sHtml * @param string $sHtml
* @param bool $bDoNotReplaceExternalUrl = false * @param bool $bDoNotReplaceExternalUrl = false
* @param bool $bFindLinksInHtml = false
* *
* @return string * @return string
*/ */
public static function ClearHtmlSimple($sHtml, $bDoNotReplaceExternalUrl = false) public static function ClearHtmlSimple($sHtml, $bDoNotReplaceExternalUrl = false, $bFindLinksInHtml = false)
{ {
$bHasExternals = false; $bHasExternals = false;
$aFoundCIDs = array(); $aFoundCIDs = array();
@ -276,7 +370,7 @@ class HtmlUtils
$aFoundedContentLocationUrls = array(); $aFoundedContentLocationUrls = array();
return \MailSo\Base\HtmlUtils::ClearHtml($sHtml, $bHasExternals, $aFoundCIDs, return \MailSo\Base\HtmlUtils::ClearHtml($sHtml, $bHasExternals, $aFoundCIDs,
$aContentLocationUrls, $aFoundedContentLocationUrls, $bDoNotReplaceExternalUrl); $aContentLocationUrls, $aFoundedContentLocationUrls, $bDoNotReplaceExternalUrl, $bFindLinksInHtml);
} }
/** /**
@ -286,11 +380,13 @@ class HtmlUtils
* @param array $aContentLocationUrls = array() * @param array $aContentLocationUrls = array()
* @param array $aFoundedContentLocationUrls = array() * @param array $aFoundedContentLocationUrls = array()
* @param bool $bDoNotReplaceExternalUrl = false * @param bool $bDoNotReplaceExternalUrl = false
* @param bool $bFindLinksInHtml = false
* *
* @return string * @return string
*/ */
public static function ClearHtml($sHtml, &$bHasExternals = false, &$aFoundCIDs = array(), public static function ClearHtml($sHtml, &$bHasExternals = false, &$aFoundCIDs = array(),
$aContentLocationUrls = array(), &$aFoundedContentLocationUrls = array(), $bDoNotReplaceExternalUrl = false) $aContentLocationUrls = array(), &$aFoundedContentLocationUrls = array(),
$bDoNotReplaceExternalUrl = false, $bFindLinksInHtml = false)
{ {
$sHtml = null === $sHtml ? '' : (string) $sHtml; $sHtml = null === $sHtml ? '' : (string) $sHtml;
$sHtml = \trim($sHtml); $sHtml = \trim($sHtml);
@ -313,11 +409,16 @@ class HtmlUtils
if ($oDom) if ($oDom)
{ {
if ($bFindLinksInHtml)
{
\MailSo\Base\HtmlUtils::FindLinksInDOM($oDom);
}
$aNodes = $oDom->getElementsByTagName('*'); $aNodes = $oDom->getElementsByTagName('*');
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{ {
$sTagNameLower = \strtolower($oElement->tagName); $sTagNameLower = \strtolower($oElement->tagName);
// convert body attributes to styles // convert body attributes to styles
if ('body' === $sTagNameLower) if ('body' === $sTagNameLower)
{ {
@ -493,6 +594,8 @@ class HtmlUtils
$sResult = '<div data-x-div-type="body" '.$sBodyAttrs.'>'.$sResult.'</div>'; $sResult = '<div data-x-div-type="body" '.$sBodyAttrs.'>'.$sResult.'</div>';
$sResult = '<div data-x-div-type="html" '.$sHtmlAttrs.'>'.$sResult.'</div>'; $sResult = '<div data-x-div-type="html" '.$sHtmlAttrs.'>'.$sResult.'</div>';
$sResult = \str_replace(\MailSo\Base\HtmlUtils::$KOS, ':', $sResult);
return \trim($sResult); return \trim($sResult);
} }
@ -658,8 +761,7 @@ class HtmlUtils
$sText = \MailSo\Base\LinkFinder::NewInstance() $sText = \MailSo\Base\LinkFinder::NewInstance()
->Text($sText) ->Text($sText)
->UseDefaultWrappers($bLinksWithTargetBlank) ->UseDefaultWrappers($bLinksWithTargetBlank)
// ->CompileText(true, false); ->CompileText();
->CompileText(true, true);
$sText = \str_replace("\r", '', $sText); $sText = \str_replace("\r", '', $sText);

View file

@ -126,13 +126,8 @@ class LinkFinder
*/ */
public function UseDefaultWrappers($bAddTargetBlank = false) public function UseDefaultWrappers($bAddTargetBlank = false)
{ {
$this->fLinkWrapper = function ($sLink, $bShortLink = false) use ($bAddTargetBlank) { $this->fLinkWrapper = function ($sLink) use ($bAddTargetBlank) {
if ($bShortLink && \in_array(\strtolower($sLink), array('asp.net', 'vb.net', 'mailbee.net')))
{
return $sLink;
}
$sNameLink = $sLink; $sNameLink = $sLink;
if (!\preg_match('/^[a-z]{3,5}\:\/\//i', \ltrim($sLink))) if (!\preg_match('/^[a-z]{3,5}\:\/\//i', \ltrim($sLink)))
{ {
@ -151,11 +146,10 @@ class LinkFinder
/** /**
* @param bool $bUseHtmlSpecialChars = true * @param bool $bUseHtmlSpecialChars = true
* @param bool $bFindShortLinks = true
* *
* @return string * @return string
*/ */
public function CompileText($bUseHtmlSpecialChars = true, $bFindShortLinks = true) public function CompileText($bUseHtmlSpecialChars = true)
{ {
$sText = \substr($this->sText, 0, $this->iOptimizationLimit); $sText = \substr($this->sText, 0, $this->iOptimizationLimit);
$sSubText = \substr($this->sText, $this->iOptimizationLimit); $sSubText = \substr($this->sText, $this->iOptimizationLimit);
@ -171,11 +165,6 @@ class LinkFinder
$sText = $this->findMails($sText, $this->fMailWrapper); $sText = $this->findMails($sText, $this->fMailWrapper);
} }
if ($bFindShortLinks && null !== $this->fLinkWrapper && \is_callable($this->fLinkWrapper))
{
$sText = $this->findShortLinks($sText, $this->fLinkWrapper);
}
$sResult = ''; $sResult = '';
if ($bUseHtmlSpecialChars) if ($bUseHtmlSpecialChars)
{ {
@ -259,46 +248,6 @@ class LinkFinder
return $sText; return $sText;
} }
/**
* @param string $sText
* @param mixed $fWrapper
*
* @return string
*/
private function findShortLinks($sText, $fWrapper)
{
$sPattern = '/([a-z0-9-\.]+\.(?:com|org|net|ru))([^a-z0-9-\.])/i';
$aPrepearPlainStringUrls = $this->aPrepearPlainStringUrls;
$sText = \preg_replace_callback($sPattern, function ($aMatch) use ($fWrapper, &$aPrepearPlainStringUrls) {
if (\is_array($aMatch) && 2 < \count($aMatch) && isset($aMatch[1]) && 0 < \strlen($aMatch[1]))
{
$sLinkWithWrap = \call_user_func_array($fWrapper, array($aMatch[1], true));
if (\is_string($sLinkWithWrap))
{
$aPrepearPlainStringUrls[] = \stripslashes($sLinkWithWrap);
return \MailSo\Base\LinkFinder::OPEN_LINK.
(\count($aPrepearPlainStringUrls) - 1).
\MailSo\Base\LinkFinder::CLOSE_LINK.
$aMatch[2];
}
return $aMatch[0];
}
return '';
}, $sText);
if (0 < \count($aPrepearPlainStringUrls))
{
$this->aPrepearPlainStringUrls = $aPrepearPlainStringUrls;
}
return $sText;
}
/** /**
* @param string $sText * @param string $sText
* @param mixed $fWrapper * @param mixed $fWrapper

View file

@ -740,7 +740,7 @@ class Utils
{ {
$sResult = ''; $sResult = '';
$sContentType = \strtolower($sContentType); $sContentType = \strtolower($sContentType);
if (0 === strpos($sContentType, 'image/')) if (0 === \strpos($sContentType, 'image/'))
{ {
$sResult = 'image'; $sResult = 'image';
} }
@ -847,7 +847,7 @@ class Utils
*/ */
public static function Php2js($mInput) public static function Php2js($mInput)
{ {
return \json_encode($mInput, defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : 0); return \json_encode($mInput, \defined('JSON_UNESCAPED_UNICODE') ? JSON_UNESCAPED_UNICODE : 0);
// if (\is_null($mInput)) // if (\is_null($mInput))
// { // {
@ -918,25 +918,25 @@ class Utils
*/ */
public static function RecRmDir($sDir) public static function RecRmDir($sDir)
{ {
if (@is_dir($sDir)) if (@\is_dir($sDir))
{ {
$aObjects = scandir($sDir); $aObjects = \scandir($sDir);
foreach ($aObjects as $sObject) foreach ($aObjects as $sObject)
{ {
if ('.' !== $sObject && '..' !== $sObject) if ('.' !== $sObject && '..' !== $sObject)
{ {
if ('dir' === filetype($sDir.'/'.$sObject)) if ('dir' === \filetype($sDir.'/'.$sObject))
{ {
self::RecRmDir($sDir.'/'.$sObject); self::RecRmDir($sDir.'/'.$sObject);
} }
else else
{ {
@unlink($sDir.'/'.$sObject); @\unlink($sDir.'/'.$sObject);
} }
} }
} }
return @rmdir($sDir); return @\rmdir($sDir);
} }
return false; return false;

View file

@ -10,7 +10,7 @@ final class Version
/** /**
* @var string * @var string
*/ */
const APP_VERSION = '1.2.2'; const APP_VERSION = '1.3.0';
/** /**
* @var string * @var string

View file

@ -6264,7 +6264,7 @@ class Actions
protected function responseObject($mResponse, $sParent = '', $aParameters = array()) protected function responseObject($mResponse, $sParent = '', $aParameters = array())
{ {
$mResult = $mResponse; $mResult = $mResponse;
if (is_object($mResponse)) if (\is_object($mResponse))
{ {
$bHook = true; $bHook = true;
$sClassName = \get_class($mResponse); $sClassName = \get_class($mResponse);
@ -6327,7 +6327,7 @@ class Actions
$sSubject = $mResult['Subject']; $sSubject = $mResult['Subject'];
$mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValues(array( $mResult['RequestHash'] = \RainLoop\Utils::EncodeKeyValues(array(
'V' => APP_VERSION, 'V' => APP_VERSION,
'Account' => $oAccount ? md5($oAccount->Hash()) : '', 'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
'Folder' => $mResult['Folder'], 'Folder' => $mResult['Folder'],
'Uid' => $mResult['Uid'], 'Uid' => $mResult['Uid'],
'MimeType' => 'message/rfc822', 'MimeType' => 'message/rfc822',
@ -6372,12 +6372,12 @@ class Actions
} }
$sPlain = ''; $sPlain = '';
$sHtml = $mResponse->Html(); $sHtml = \trim($mResponse->Html());
$bRtl = false; $bRtl = false;
if (0 === \strlen($sHtml)) if (0 === \strlen($sHtml))
{ {
$sPlain = $mResponse->Plain(); $sPlain = \trim($mResponse->Plain());
$bRtl = \MailSo\Base\Utils::IsRTL($sPlain); $bRtl = \MailSo\Base\Utils::IsRTL($sPlain);
} }
else else
@ -6389,7 +6389,8 @@ class Actions
$mResult['InReplyTo'] = $mResponse->InReplyTo(); $mResult['InReplyTo'] = $mResponse->InReplyTo();
$mResult['References'] = $mResponse->References(); $mResult['References'] = $mResponse->References();
$mResult['Html'] = 0 === \strlen($sHtml) ? '' : \MailSo\Base\HtmlUtils::ClearHtml( $mResult['Html'] = 0 === \strlen($sHtml) ? '' : \MailSo\Base\HtmlUtils::ClearHtml(
$sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls); $sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls, false,
!!$this->Config()->Get('labs', 'allow_smart_html_links', true));
$mResult['PlainRaw'] = $sPlain; $mResult['PlainRaw'] = $sPlain;
$mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain); $mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain);
@ -6418,7 +6419,7 @@ class Actions
try try
{ {
$oReadReceipt = \MailSo\Mime\Email::Parse($mResult['ReadReceipt']); $oReadReceipt = \MailSo\Mime\Email::Parse($mResult['ReadReceipt']);
if ($oReadReceipt && \strtolower($oAccount->Email()) === \strtolower($oReadReceipt->GetEmail())) if (!$oReadReceipt || ($oReadReceipt && \strtolower($oAccount->Email()) === \strtolower($oReadReceipt->GetEmail())))
{ {
$mResult['ReadReceipt'] = ''; $mResult['ReadReceipt'] = '';
} }
@ -6495,13 +6496,13 @@ class Actions
'CID' => $mResponse->Cid(), 'CID' => $mResponse->Cid(),
'ContentLocation' => $mResponse->ContentLocation(), 'ContentLocation' => $mResponse->ContentLocation(),
'IsInline' => $mResponse->IsInline(), 'IsInline' => $mResponse->IsInline(),
'IsLinked' => ($mFoundedCIDs && \in_array(trim(trim($mResponse->Cid()), '<>'), $mFoundedCIDs)) || 'IsLinked' => ($mFoundedCIDs && \in_array(\trim(\trim($mResponse->Cid()), '<>'), $mFoundedCIDs)) ||
($mFoundedContentLocationUrls && \in_array(\trim($mResponse->ContentLocation()), $mFoundedContentLocationUrls)) ($mFoundedContentLocationUrls && \in_array(\trim($mResponse->ContentLocation()), $mFoundedContentLocationUrls))
)); ));
$mResult['Download'] = \RainLoop\Utils::EncodeKeyValues(array( $mResult['Download'] = \RainLoop\Utils::EncodeKeyValues(array(
'V' => APP_VERSION, 'V' => APP_VERSION,
'Account' => $oAccount ? md5($oAccount->Hash()) : '', 'Account' => $oAccount ? \md5($oAccount->Hash()) : '',
'Folder' => $mResult['Folder'], 'Folder' => $mResult['Folder'],
'Uid' => $mResult['Uid'], 'Uid' => $mResult['Uid'],
'MimeIndex' => $mResult['MimeIndex'], 'MimeIndex' => $mResult['MimeIndex'],
@ -6513,7 +6514,7 @@ class Actions
{ {
$aExtended = null; $aExtended = null;
$mStatus = $mResponse->Status(); $mStatus = $mResponse->Status();
if (is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'])) if (\is_array($mStatus) && isset($mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT']))
{ {
$aExtended = array( $aExtended = array(
'MessageCount' => (int) $mStatus['MESSAGES'], 'MessageCount' => (int) $mStatus['MESSAGES'],
@ -6524,7 +6525,7 @@ class Actions
); );
} }
$mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
'Name' => $mResponse->Name(), 'Name' => $mResponse->Name(),
'FullName' => $mResponse->FullName(), 'FullName' => $mResponse->FullName(),
'FullNameRaw' => $mResponse->FullNameRaw(), 'FullNameRaw' => $mResponse->FullNameRaw(),
@ -6541,7 +6542,7 @@ class Actions
} }
else if ('MailSo\Mail\MessageCollection' === $sClassName) else if ('MailSo\Mail\MessageCollection' === $sClassName)
{ {
$mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
'MessageCount' => $mResponse->MessageCount, 'MessageCount' => $mResponse->MessageCount,
'MessageUnseenCount' => $mResponse->MessageUnseenCount, 'MessageUnseenCount' => $mResponse->MessageUnseenCount,
'MessageResultCount' => $mResponse->MessageResultCount, 'MessageResultCount' => $mResponse->MessageResultCount,
@ -6557,13 +6558,13 @@ class Actions
} }
else if ('MailSo\Mail\AttachmentCollection' === $sClassName) else if ('MailSo\Mail\AttachmentCollection' === $sClassName)
{ {
$mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
'InlineCount' => $mResponse->InlineCount() 'InlineCount' => $mResponse->InlineCount()
)); ));
} }
else if ('MailSo\Mail\FolderCollection' === $sClassName) else if ('MailSo\Mail\FolderCollection' === $sClassName)
{ {
$mResult = array_merge($this->objectData($mResponse, $sParent, $aParameters), array( $mResult = \array_merge($this->objectData($mResponse, $sParent, $aParameters), array(
'Namespace' => $mResponse->GetNamespace(), 'Namespace' => $mResponse->GetNamespace(),
'FoldersHash' => isset($mResponse->FoldersHash) ? $mResponse->FoldersHash : '', 'FoldersHash' => isset($mResponse->FoldersHash) ? $mResponse->FoldersHash : '',
'IsThreadsSupported' => $mResponse->IsThreadsSupported, 'IsThreadsSupported' => $mResponse->IsThreadsSupported,
@ -6579,7 +6580,7 @@ class Actions
} }
else else
{ {
$mResult = '['.get_class($mResponse).']'; $mResult = '['.\get_class($mResponse).']';
$bHook = false; $bHook = false;
} }
@ -6588,7 +6589,7 @@ class Actions
$this->Plugins()->RunHook('filter.response-object', array($sClassName, $mResult), false); $this->Plugins()->RunHook('filter.response-object', array($sClassName, $mResult), false);
} }
} }
else if (is_array($mResponse)) else if (\is_array($mResponse))
{ {
foreach ($mResponse as $iKey => $oItem) foreach ($mResponse as $iKey => $oItem)
{ {

View file

@ -1,252 +1,253 @@
<?php <?php
namespace RainLoop\Config; namespace RainLoop\Config;
class Application extends \RainLoop\Config\AbstractConfig class Application extends \RainLoop\Config\AbstractConfig
{ {
/** /**
* @return void * @return void
*/ */
public function __construct() public function __construct()
{ {
parent::__construct('application.ini', parent::__construct('application.ini',
'; RainLoop Webmail configuration file '; RainLoop Webmail configuration file
; Please don\'t add custom parameters here, those will be overwritten'); ; Please don\'t add custom parameters here, those will be overwritten');
} }
/** /**
* @param string $sPassword * @param string $sPassword
* *
* @return void * @return void
*/ */
public function SetPassword($sPassword) public function SetPassword($sPassword)
{ {
return $this->Set('security', 'admin_password', \md5(APP_SALT.$sPassword.APP_SALT)); return $this->Set('security', 'admin_password', \md5(APP_SALT.$sPassword.APP_SALT));
} }
/** /**
* @param string $sPassword * @param string $sPassword
* *
* @return bool * @return bool
*/ */
public function ValidatePassword($sPassword) public function ValidatePassword($sPassword)
{ {
$sPassword = (string) $sPassword; $sPassword = (string) $sPassword;
$sConfigPassword = (string) $this->Get('security', 'admin_password', ''); $sConfigPassword = (string) $this->Get('security', 'admin_password', '');
return 0 < \strlen($sPassword) && return 0 < \strlen($sPassword) &&
($sPassword === $sConfigPassword || \md5(APP_SALT.$sPassword.APP_SALT) === $sConfigPassword); ($sPassword === $sConfigPassword || \md5(APP_SALT.$sPassword.APP_SALT) === $sConfigPassword);
} }
/** /**
* @return bool * @return bool
*/ */
public function Save() public function Save()
{ {
$this->Set('version', 'current', APP_VERSION); $this->Set('version', 'current', APP_VERSION);
$this->Set('version', 'saved', \gmdate('r')); $this->Set('version', 'saved', \gmdate('r'));
return parent::Save(); return parent::Save();
} }
/** /**
* @return array * @return array
*/ */
protected function defaultValues() protected function defaultValues()
{ {
return array( return array(
'webmail' => array( 'webmail' => array(
'title' => array('RainLoop Webmail', 'Text displayed as page title'), 'title' => array('RainLoop Webmail', 'Text displayed as page title'),
'loading_description' => array('RainLoop', 'Text displayed on startup'), 'loading_description' => array('RainLoop', 'Text displayed on startup'),
'theme' => array('Default', 'Theme used by default'), 'theme' => array('Default', 'Theme used by default'),
'allow_themes' => array(true, 'Allow theme selection on settings screen'), 'allow_themes' => array(true, 'Allow theme selection on settings screen'),
'allow_custom_theme' => array(true, ''), 'allow_custom_theme' => array(true, ''),
'language' => array('en', 'Language used by default'), 'language' => array('en', 'Language used by default'),
'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'), 'allow_languages_on_settings' => array(true, 'Allow language selection on settings screen'),
'allow_additional_accounts' => array(true, ''), 'allow_additional_accounts' => array(true, ''),
'allow_identities' => array(true, ''), 'allow_identities' => array(true, ''),
'messages_per_page' => array(20, ' Number of messages displayed on page by default'), 'messages_per_page' => array(20, ' Number of messages displayed on page by default'),
'editor_default_type' => array('Html', 'Editor mode used by default (Html or Plain)'), 'editor_default_type' => array('Html', 'Editor mode used by default (Html or Plain)'),
'attachment_size_limit' => array(5, 'attachment_size_limit' => array(5,
'File size limit (MB) for file upload on compose screen 'File size limit (MB) for file upload on compose screen
0 for unlimited.') 0 for unlimited.')
), ),
'branding' => array( 'branding' => array(
'login_logo' => array(''), 'login_logo' => array(''),
'login_desc' => array(''), 'login_desc' => array(''),
'login_css' => array(''), 'login_css' => array(''),
), ),
'contacts' => array( 'contacts' => array(
'enable' => array(false, 'Enable contacts'), 'enable' => array(false, 'Enable contacts'),
'allow_sharing' => array(true), 'allow_sharing' => array(true),
'allow_sync' => array(false), 'allow_sync' => array(false),
'suggestions_limit' => array(30), 'suggestions_limit' => array(30),
'type' => array('sqlite', ''), 'type' => array('sqlite', ''),
'pdo_dsn' => array('mysql:host=127.0.0.1;port=3306;dbname=rainloop', ''), 'pdo_dsn' => array('mysql:host=127.0.0.1;port=3306;dbname=rainloop', ''),
'pdo_user' => array('root', ''), 'pdo_user' => array('root', ''),
'pdo_password' => array('', ''), 'pdo_password' => array('', ''),
), ),
'security' => array( 'security' => array(
'csrf_protection' => array(true, 'csrf_protection' => array(true,
'Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)'), 'Enable CSRF protection (http://en.wikipedia.org/wiki/Cross-site_request_forgery)'),
'custom_server_signature' => array('RainLoop'), 'custom_server_signature' => array('RainLoop'),
'openpgp' => array(false), 'openpgp' => array(false),
'admin_login' => array('admin', 'Login and password for web admin panel'), 'admin_login' => array('admin', 'Login and password for web admin panel'),
'admin_password' => array('12345'), 'admin_password' => array('12345'),
'allow_admin_panel' => array(true, 'Access settings'), 'allow_admin_panel' => array(true, 'Access settings'),
'admin_panel_host' => array(''), 'admin_panel_host' => array(''),
'core_install_access_domains' => array('') 'core_install_access_domains' => array('')
), ),
'login' => array( 'login' => array(
'allow_custom_login' => array(false, 'allow_custom_login' => array(false,
'Enable additional Login field on webmail login screen'), 'Enable additional Login field on webmail login screen'),
'default_domain' => array('', ''), 'default_domain' => array('', ''),
'allow_languages_on_login' => array(true, 'allow_languages_on_login' => array(true,
'Allow language selection on webmail login screen'), 'Allow language selection on webmail login screen'),
'sign_me_auto' => array(\RainLoop\Enumerations\SignMeType::DEFAILT_OFF, 'sign_me_auto' => array(\RainLoop\Enumerations\SignMeType::DEFAILT_OFF,
'This option allows webmail to remember the logged in user 'This option allows webmail to remember the logged in user
once they closed the browser window. once they closed the browser window.
Values: Values:
"DefaultOff" - can be used, disabled by default; "DefaultOff" - can be used, disabled by default;
"DefaultOn" - can be used, enabled by default; "DefaultOn" - can be used, enabled by default;
"Unused" - cannot be used') "Unused" - cannot be used')
), ),
'plugins' => array( 'plugins' => array(
'enable' => array(false, 'Enable plugin support'), 'enable' => array(false, 'Enable plugin support'),
'enabled_list' => array('', 'List of enabled plugins'), 'enabled_list' => array('', 'List of enabled plugins'),
), ),
'logs' => array( 'logs' => array(
'enable' => array(false, 'Enable logging'), 'enable' => array(false, 'Enable logging'),
'write_on_error_only' => array(false, 'Logs entire request only if error occured'), 'write_on_error_only' => array(false, 'Logs entire request only if error occured'),
'filename' => array('log-{date:Y-m-d}.txt', 'filename' => array('log-{date:Y-m-d}.txt',
'Log filename. 'Log filename.
For security reasons, some characters are removed from filename. For security reasons, some characters are removed from filename.
Allows for pattern-based folder creation (see examples below). Allows for pattern-based folder creation (see examples below).
Patterns: Patterns:
{date:Y-m-d} - Replaced by pattern-based date {date:Y-m-d} - Replaced by pattern-based date
Detailed info: http://www.php.net/manual/en/function.date.php Detailed info: http://www.php.net/manual/en/function.date.php
{user:email} - Replaced by user\'s email address {user:email} - Replaced by user\'s email address
If user is not logged in, value is set to "unknown" If user is not logged in, value is set to "unknown"
{user:login} - Replaced by user\'s login {user:login} - Replaced by user\'s login
If user is not logged in, value is set to "unknown" If user is not logged in, value is set to "unknown"
{user:domain} - Replaced by user\'s domain name {user:domain} - Replaced by user\'s domain name
If user is not logged in, value is set to "unknown" If user is not logged in, value is set to "unknown"
{user:uid} - Replaced by user\'s UID regardless of account currently used {user:uid} - Replaced by user\'s UID regardless of account currently used
Examples: Examples:
filename = "log-{date:Y-m-d}.txt" filename = "log-{date:Y-m-d}.txt"
filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log" filename = "{date:Y-m-d}/{user:domain}/{user:email}_{user:uid}.log"
filename = "{user:email}-{date:Y-m-d}.txt"') filename = "{user:email}-{date:Y-m-d}.txt"')
), ),
'debug' => array( 'debug' => array(
'enable' => array(false, 'Special option required for development purposes'), 'enable' => array(false, 'Special option required for development purposes'),
), ),
'version' => array( 'version' => array(
'current' => array(''), 'current' => array(''),
'saved' => array('') 'saved' => array('')
), ),
'social' => array( 'social' => array(
'google_enable' => array(false, 'Google'), 'google_enable' => array(false, 'Google'),
'google_client_id' => array(''), 'google_client_id' => array(''),
'google_client_secret' => array(''), 'google_client_secret' => array(''),
'fb_enable' => array(false, 'Facebook'), 'fb_enable' => array(false, 'Facebook'),
'fb_app_id' => array(''), 'fb_app_id' => array(''),
'fb_app_secret' => array(''), 'fb_app_secret' => array(''),
'twitter_enable' => array(false, 'Twitter'), 'twitter_enable' => array(false, 'Twitter'),
'twitter_consumer_key' => array(''), 'twitter_consumer_key' => array(''),
'twitter_consumer_secret' => array(''), 'twitter_consumer_secret' => array(''),
'dropbox_enable' => array(false, 'Dropbox'), 'dropbox_enable' => array(false, 'Dropbox'),
'dropbox_api_key' => array(''), 'dropbox_api_key' => array(''),
), ),
'cache' => array( 'cache' => array(
'enable' => array(true, 'enable' => array(true,
'The section controls caching of the entire application. 'The section controls caching of the entire application.
Enables caching in the system'), Enables caching in the system'),
'index' => array('v1', 'Additional caching key. If changed, cache is purged'), 'index' => array('v1', 'Additional caching key. If changed, cache is purged'),
'fast_cache_driver' => array('files', 'Can be: files, APC, memcache'), 'fast_cache_driver' => array('files', 'Can be: files, APC, memcache'),
'fast_cache_index' => array('v1', 'Additional caching key. If changed, fast cache is purged'), 'fast_cache_index' => array('v1', 'Additional caching key. If changed, fast cache is purged'),
'http' => array(true, 'Browser-level cache. If enabled, caching is maintainted without using files'), 'http' => array(true, 'Browser-level cache. If enabled, caching is maintainted without using files'),
'server_uids' => array(false, 'Caching message UIDs when searching and sorting (threading)') 'server_uids' => array(false, 'Caching message UIDs when searching and sorting (threading)')
), ),
'labs' => array( 'labs' => array(
'ignore_folders_subscription' => array(false, 'ignore_folders_subscription' => array(false,
'Experimental settings. Handle with care. 'Experimental settings. Handle with care.
'), '),
'sync_dav_digest_auth' => array(true), 'allow_prefetch' => array(true),
'sync_dav_domain' => array(''), 'allow_smart_html_links' => array(true),
'sync_use_dav_browser' => array(true), 'cache_system_data' => array(true),
'allow_message_append' => array(false), 'date_from_headers' => array(false),
'date_from_headers' => array(false), 'autocreate_system_folders' => array(true),
'cache_system_data' => array(true), 'allow_message_append' => array(false),
'use_app_debug_js' => array(false), 'determine_user_language' => array(true),
'use_app_debug_css' => array(false), 'login_fault_delay' => array(1),
'use_dav_digest_auth' => array(false), 'log_ajax_response_write_limit' => array(300),
'login_fault_delay' => array(1), 'sync_dav_digest_auth' => array(true),
'log_ajax_response_write_limit' => array(300), 'sync_dav_domain' => array(''),
'determine_user_language' => array(true), 'sync_use_dav_browser' => array(true),
'use_imap_sort' => array(false), 'use_app_debug_js' => array(false),
'use_imap_force_selection' => array(false), 'use_app_debug_css' => array(false),
'use_imap_list_subscribe' => array(true), 'use_imap_sort' => array(false),
'use_imap_thread' => array(true), 'use_imap_force_selection' => array(false),
'use_imap_move' => array(true), 'use_imap_list_subscribe' => array(true),
'use_imap_auth_plain' => array(false), 'use_imap_thread' => array(true),
'imap_forwarded_flag' => array('$Forwarded'), 'use_imap_move' => array(true),
'imap_read_receipt_flag' => array('$ReadReceipt'), 'use_imap_auth_plain' => array(false),
'smtp_show_server_errors' => array(false), 'imap_forwarded_flag' => array('$Forwarded'),
'allow_prefetch' => array(true), 'imap_read_receipt_flag' => array('$ReadReceipt'),
'autocreate_system_folders' => array(true), 'smtp_show_server_errors' => array(false),
'repo_type' => array('stable'), 'repo_type' => array('stable'),
'custom_repo' => array(''), 'custom_repo' => array(''),
'additional_repo' => array(''), 'additional_repo' => array(''),
'cdn_static_domain' => array(''), 'cdn_static_domain' => array(''),
'curl_proxy' => array(''), 'curl_proxy' => array(''),
'curl_proxy_auth' => array(''), 'curl_proxy_auth' => array(''),
'in_iframe' => array(false), 'in_iframe' => array(false),
'custom_login_link' => array(''), 'custom_login_link' => array(''),
'custom_logout_link' => array(''), 'custom_logout_link' => array(''),
'allow_external_login' => array(false), 'allow_external_login' => array(false),
'fast_cache_memcache_host' => array('127.0.0.1'), 'in_iframe' => array(false),
'fast_cache_memcache_port' => array(11211), 'fast_cache_memcache_host' => array('127.0.0.1'),
'fast_cache_memcache_expire' => array(43200), 'fast_cache_memcache_port' => array(11211),
'dev_email' => array(''), 'fast_cache_memcache_expire' => array(43200),
'dev_login' => array(''), 'dev_email' => array(''),
'dev_password' => array('') 'dev_login' => array(''),
) 'dev_password' => array('')
); )
} );
} }
}