diff --git a/core/htmlsanitizer.class.inc.php b/core/htmlsanitizer.class.inc.php
index b1076cfdf..025c3a3e8 100644
--- a/core/htmlsanitizer.class.inc.php
+++ b/core/htmlsanitizer.class.inc.php
@@ -243,10 +243,15 @@ class HTMLDOMSanitizer extends HTMLSanitizer
{
// Regular urls
$sUrlPattern = utils::GetConfig()->Get('url_validation_pattern');
+
// Mailto urls
$sMailtoPattern = '(mailto:(' . utils::GetConfig()->Get('email_validation_pattern') . ')(?:\?(?:subject|body)=([a-zA-Z0-9+\$_.-]*)(?:&(?:subject|body)=([a-zA-Z0-9+\$_.-]*))?)?)';
- $sPattern = $sUrlPattern . '|' . $sMailtoPattern;
+ // Notification placeholders
+ // eg. $this->caller_id$, $this->hyperlink()$, $this->hyperlink(portal)$, $APP_URL$, $MODULES_URL$, ...
+ $sPlaceholderPattern = '\$[\w-]*(->[\w]*(\([\w-]*?\))?)?\$';
+
+ $sPattern = $sUrlPattern . '|' . $sMailtoPattern . '|' . $sPlaceholderPattern;
$sPattern = '/'.str_replace('/', '\/', $sPattern).'/i';
self::$aAttrsWhiteList['href'] = $sPattern;
}
diff --git a/core/metamodel.class.php b/core/metamodel.class.php
index 215805948..bfdb61da4 100644
--- a/core/metamodel.class.php
+++ b/core/metamodel.class.php
@@ -7244,6 +7244,10 @@ abstract class MetaModel
{
// Expand the parameters for the object
$sName = substr($sSearch, 0, $iPos);
+ // Note: Capturing
+ // 1 - The delimiter
+ // 2 - The arrow
+ // 3 - The attribute code
$aRegExps = array(
'/(\\$)'.$sName.'-(>|>)([^\\$]+)\\$/', // Support both syntaxes: $this->xxx$ or $this->xxx$ for HTML compatibility
'/(%24)'.$sName.'-(>|>)([^%24]+)%24/', // Support for urlencoded in HTML attributes (%20this->xxx%20)
@@ -7278,8 +7282,28 @@ abstract class MetaModel
}
else
{
- $aSearches[] = '$'.$sSearch.'$';
- $aReplacements[] = (string)$replace;
+ $aRegExps = array(
+ '/(\$)'.$sSearch.'\$/', // Support for regular placeholders (eg. $APP_URL$)
+ '/(%24)'.$sSearch.'%24/', // Support for urlencoded in HTML attributes (eg. %24APP_URL%24)
+ );
+ foreach($aRegExps as $sRegExp)
+ {
+ if(preg_match_all($sRegExp, $sInput, $aMatches))
+ {
+ foreach($aMatches[1] as $idx => $sDelimiter)
+ {
+ try
+ {
+ $aReplacements[] = (string) $replace;
+ $aSearches[] = $aMatches[1][$idx] . $sSearch . $aMatches[1][$idx];
+ }
+ catch(Exception $e)
+ {
+ // No replacement will occur
+ }
+ }
+ }
+ }
}
}
return str_replace($aSearches, $aReplacements, $sInput);