Added "use_local_proxy_for_external_images" setting (Closes #211)

This commit is contained in:
RainLoop Team 2014-06-26 02:40:26 +04:00
parent a19e19d866
commit 3ae18e76c6
16 changed files with 230 additions and 43 deletions

View file

@ -150,16 +150,22 @@ class HtmlUtils
* @param array $aContentLocationUrls
* @param array $aFoundedContentLocationUrls
* @param bool $bDoNotReplaceExternalUrl = false
* @param callback|null $fAdditionalExternalFilter = null
*
* @return string
*/
public static function ClearStyle($sStyle, $oElement, &$bHasExternals, &$aFoundCIDs,
$aContentLocationUrls, &$aFoundedContentLocationUrls, $bDoNotReplaceExternalUrl = false)
$aContentLocationUrls, &$aFoundedContentLocationUrls, $bDoNotReplaceExternalUrl = false, $fAdditionalExternalFilter = null)
{
$sStyle = \trim($sStyle);
$aOutStyles = array();
$aStyles = \explode(';', $sStyle);
if ($fAdditionalExternalFilter && !\is_callable($fAdditionalExternalFilter))
{
$fAdditionalExternalFilter = null;
}
$aMatch = array();
foreach ($aStyles as $sStyleItem)
{
@ -236,6 +242,16 @@ class HtmlUtils
$oElement->setAttribute('data-x-style-url', \trim($sTemp.
('background' === $sName ? 'background-image' : $sName).': '.$sFullUrl, ' ;'));
if ($fAdditionalExternalFilter)
{
$sAdditionalResult = \call_user_func($fAdditionalExternalFilter, $sUrl);
if (0 < \strlen($sAdditionalResult))
{
$oElement->setAttribute('data-x-additional-style-url',
('background' === $sName ? 'background-image' : $sName).': url('.$sAdditionalResult.')');
}
}
}
}
else if ('data:image/' !== \strtolower(\substr(\trim($sUrl), 0, 11)))
@ -382,12 +398,13 @@ class HtmlUtils
* @param array $aFoundedContentLocationUrls = array()
* @param bool $bDoNotReplaceExternalUrl = false
* @param bool $bFindLinksInHtml = false
* @param callback|null $fAdditionalExternalFilter = null
*
* @return string
*/
public static function ClearHtml($sHtml, &$bHasExternals = false, &$aFoundCIDs = array(),
$aContentLocationUrls = array(), &$aFoundedContentLocationUrls = array(),
$bDoNotReplaceExternalUrl = false, $bFindLinksInHtml = false)
$bDoNotReplaceExternalUrl = false, $bFindLinksInHtml = false, $fAdditionalExternalFilter = null)
{
$sHtml = null === $sHtml ? '' : (string) $sHtml;
$sHtml = \trim($sHtml);
@ -396,6 +413,11 @@ class HtmlUtils
return '';
}
if ($fAdditionalExternalFilter && !\is_callable($fAdditionalExternalFilter))
{
$fAdditionalExternalFilter = null;
}
$bHasExternals = false;
$sHtml = \MailSo\Base\HtmlUtils::ClearTags($sHtml);
@ -554,6 +576,14 @@ class HtmlUtils
else
{
$oElement->setAttribute('data-x-src', $sSrc);
if ($fAdditionalExternalFilter)
{
$sResult = \call_user_func($fAdditionalExternalFilter, $sSrc);
if (0 < \strlen($sResult))
{
$oElement->setAttribute('data-x-additional-src', $sResult);
}
}
}
$bHasExternals = true;
@ -599,7 +629,7 @@ class HtmlUtils
{
$oElement->setAttribute('style',
\MailSo\Base\HtmlUtils::ClearStyle($oElement->getAttribute('style'), $oElement, $bHasExternals,
$aFoundCIDs, $aContentLocationUrls, $aFoundedContentLocationUrls, $bDoNotReplaceExternalUrl));
$aFoundCIDs, $aContentLocationUrls, $aFoundedContentLocationUrls, $bDoNotReplaceExternalUrl, $fAdditionalExternalFilter));
}
}
@ -684,6 +714,16 @@ class HtmlUtils
$oElement->removeAttribute('data-x-href');
}
if ($oElement->hasAttribute('data-x-additional-src'))
{
$oElement->removeAttribute('data-x-additional-src');
}
if ($oElement->hasAttribute('data-x-additional-style-url'))
{
$oElement->removeAttribute('data-x-additional-style-url');
}
if ($oElement->hasAttribute('data-x-style-cid-name') && $oElement->hasAttribute('data-x-style-cid'))
{
$sCidName = $oElement->getAttribute('data-x-style-cid-name');

View file

@ -1215,6 +1215,7 @@ class Actions
$aResult['AllowLanguagesOnLogin'] = (bool) $oConfig->Get('login', 'allow_languages_on_login', true);
$aResult['AttachmentLimit'] = ((int) $oConfig->Get('webmail', 'attachment_size_limit', 10)) * 1024 * 1024;
$aResult['SignMe'] = (string) $oConfig->Get('login', 'sign_me_auto', \RainLoop\Enumerations\SignMeType::DEFAILT_OFF);
$aResult['UseLocalProxyForExternalImages'] = (bool) $oConfig->Get('labs', 'use_local_proxy_for_external_images', false);
// user
$aResult['EditorDefaultType'] = (string) $oConfig->Get('webmail', 'editor_default_type', '');
@ -2172,6 +2173,8 @@ class Actions
return $self->ValidateTheme($sTheme);
});
$this->setConfigFromParams($oConfig, 'UseLocalProxyForExternalImages', 'labs', 'use_local_proxy_for_external_images', 'bool');
$this->setConfigFromParams($oConfig, 'AllowLanguagesOnSettings', 'webmail', 'allow_languages_on_settings', 'bool');
$this->setConfigFromParams($oConfig, 'AllowLanguagesOnLogin', 'login', 'allow_languages_on_login', 'bool');
$this->setConfigFromParams($oConfig, 'AttachmentLimit', 'webmail', 'attachment_size_limit', 'int');
@ -7009,6 +7012,7 @@ class Actions
'ThreadsLen' => $mResponse->ThreadsLen(),
'ParentThread' => $mResponse->ParentThread(),
'Sensitivity' => $mResponse->Sensitivity(),
'ExternalProxy' => false,
'ReadReceipt' => ''
));
@ -7095,9 +7099,24 @@ class Actions
$mResult['DraftInfo'] = $mResponse->DraftInfo();
$mResult['InReplyTo'] = $mResponse->InReplyTo();
$mResult['References'] = $mResponse->References();
$fAdditionalExternalFilter = null;
if (!!$this->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
{
$sIndexPrefix = 0 < strlen(APP_INDEX_FILE) ? APP_INDEX_FILE : './';
$fAdditionalExternalFilter = function ($sUrl) use ($sIndexPrefix) {
return $sIndexPrefix.'?/ProxyExternal/'.\RainLoop\Utils::EncodeKeyValues(array(
'Token' => \RainLoop\Utils::GetConnectionToken(),
'Url' => $sUrl
)).'/';
};
}
$mResult['Html'] = 0 === \strlen($sHtml) ? '' : \MailSo\Base\HtmlUtils::ClearHtml(
$sHtml, $bHasExternals, $mFoundedCIDs, $aContentLocationUrls, $mFoundedContentLocationUrls, false,
!!$this->Config()->Get('labs', 'allow_smart_html_links', true));
!!$this->Config()->Get('labs', 'allow_smart_html_links', true), $fAdditionalExternalFilter);
$mResult['ExternalProxy'] = null !== $fAdditionalExternalFilter;
$mResult['PlainRaw'] = $sPlain;
$mResult['Plain'] = 0 === \strlen($sPlain) ? '' : \MailSo\Base\HtmlUtils::ConvertPlainToHtml($sPlain);

View file

@ -245,6 +245,7 @@ Enables caching in the system'),
'fast_cache_memcache_host' => array('127.0.0.1'),
'fast_cache_memcache_port' => array(11211),
'fast_cache_memcache_expire' => array(43200),
'use_local_proxy_for_external_images' => array(false),
'dev_email' => array(''),
'dev_password' => array('')
)

View file

@ -337,6 +337,66 @@ class ServiceActions
return $this->privateUpload('UploadBackground');
}
/**
* @return string
*/
public function ServiceProxyExternal()
{
$bResult = false;
$sData = empty($this->aPaths[1]) ? '' : $this->aPaths[1];
if (!empty($sData) && $this->oActions->Config()->Get('labs', 'use_local_proxy_for_external_images', false))
{
$this->oActions->verifyCacheByKey($sData);
$aData = \RainLoop\Utils::DecodeKeyValues($sData);
if (\is_array($aData) && !empty($aData['Token']) && !empty($aData['Url']) && $aData['Token'] === \RainLoop\Utils::GetConnectionToken())
{
$sUrl = $aData['Url'];
$aOptions = array(
CURLOPT_URL => $sUrl,
CURLOPT_HEADER => false,
CURLOPT_USERAGENT => 'RainLoop External Proxy',
CURLOPT_FAILONERROR => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => false,
CURLOPT_TIMEOUT => (int) 10
);
$oCurl = \curl_init();
\curl_setopt_array($oCurl, $aOptions);
$mResult = \curl_exec($oCurl);
$iCode = (int) \curl_getinfo($oCurl, CURLINFO_HTTP_CODE);
$sContentType = (string) \curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE);
$sContentType = \trim(\strtolower($sContentType));
if (false !== $mResult && 200 === $iCode &&
\in_array($sContentType, array('image/png', 'image/jpeg', 'image/jpg', 'image/bmp', 'image/gif')))
{
$bResult = true;
$this->oActions->cacheByKey($sData);
\header('Content-Type: '.$sContentType);
echo $mResult;
}
if (\is_resource($oCurl))
{
\curl_close($oCurl);
}
}
}
if (!$bResult)
{
$this->oHttp->StatusHeader(404);
}
}
/**
* @return string
*/

View file

@ -8,7 +8,8 @@
<label data-bind="click: function () { capaOpenPGP(!capaOpenPGP()); }">
<i data-bind="css: capaOpenPGP() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
&nbsp;&nbsp;
Allow OpenPGP <span style="color:red">(beta)</span>
Allow OpenPGP
<span style="color:red">(beta)</span>
</label>
</div>
</div>
@ -21,6 +22,16 @@
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label data-bind="click: function () { useLocalProxyForExternalImages(!useLocalProxyForExternalImages()); }">
<i data-bind="css: useLocalProxyForExternalImages() ? 'icon-checkbox-checked' : 'icon-checkbox-unchecked'"></i>
&nbsp;&nbsp;
Use local proxy for external images
<span style="color:red">(beta)</span>
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<a href="#" target="_blank" class="g-ui-link" data-bind="link: phpInfoLink()">Show PHP information</a>