Skip to content

Instantly share code, notes, and snippets.

@totten
Last active October 15, 2019 00:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save totten/5b30e10a21fe626a43a30e21ded26fc4 to your computer and use it in GitHub Desktop.
Save totten/5b30e10a21fe626a43a30e21ded26fc4 to your computer and use it in GitHub Desktop.
(POC) Auto-escaping in Smarty v2
<?php
// FILE: CRM/Core/Smarty/plugins/modifier.crmEscape.php
/**
* Escape a string
*
* @param string $string
* String to display
* @param string $esc_type
* Ex: 'html', 'none', 'url'.
* @param string $char_set
*
* @return string
* Escaped string.
*/
function smarty_modifier_crmEscape($string, $esc_type = 'html', $char_set = 'ISO-8859-1') {
require_once 'packages/Smarty/plugins/modifier.escape.php';
if ($esc_type === 'none') {
return $string;
}
else {
return smarty_modifier_escape($string, $esc_type, $char_set);
}
}
<?php
// This is a demonstration of auto-escaping in Smarty v2.
// Run it with `cv scr smarty-pre.php`
$files = [
"string:
Automatic, form element: {\$form.widget.html}
Automatic, data: {\$data.foo}
Explicit, HTML encoded: {\$data.foo|crmEscape:html}
Explicit, unencoded: {\$data.foo|crmEscape:none}
",
];
class ValueFilters {
public static function wrapExpressions($tpl_source, &$smarty, $cb) {
// printf("== prefilter($cb): start ==\n%s\n\n", $tpl_source);
$oldHead = preg_quote('{$', '/');
$oldFoot = preg_quote('}', '/');
$func = function ($m) use ($cb) {
// print_r(['m'=>$m]);
return $cb($m[0]);
};
$tpl_source = preg_replace_callback("/{$oldHead}([^\{\}]+){$oldFoot}/", $func, $tpl_source);
// printf("== prefilter($cb): end ==\n%s\n==\n\n", $tpl_source);
return $tpl_source;
}
public static function autoEscape($tpl_source, &$smarty) {
return self::wrapExpressions($tpl_source, $smarty, function ($expr) {
if (
strpos($expr, '|@count') !== FALSE
|| strpos($expr, '|@json') !== FALSE
|| strpos($expr, '|@json_encode') !== FALSE
|| strpos($expr, '|colorContrast') !== FALSE
|| strpos($expr, '|crmDate') !== FALSE
|| strpos($expr, '|crmEscape:') !== FALSE
|| strpos($expr, '|crmICalText') !== FALSE
|| strpos($expr, '|crmICalDate') !== FALSE
|| strpos($expr, '|crmMoney') !== FALSE
|| strpos($expr, '|crmNumberFormat') !== FALSE
|| strpos($expr, '|date_format:') !== FALSE
|| strpos($expr, '|escape:') !== FALSE
|| strpos($expr, '|htmlentities') !== FALSE
|| strpos($expr, '|htmlspecialchars') !== FALSE
|| strpos($expr, '|intval') !== FALSE
|| strpos($expr, '|json_encode') !== FALSE
|| strpos($expr, '|string_format:') !== FALSE
|| strpos($expr, '|strip_tags') !== FALSE
|| preg_match('/form\.[^\|]+\.html/', $expr)
) {
return $expr;
}
else {
return substr($expr, 0, -1) . '|crmEscape:html}';
}
});
}
}
$s = CRM_Core_Smarty::singleton();
$s->register_prefilter(['ValueFilters', 'autoEscape']);
$s->assign('data', [
'foo' => 'Alice <alice@example.org>',
]);
$s->assign('form', [
'widget' => ['html' => '<div class="crm-foo-bar"></div>'],
]);
foreach ($files as $file) {
$d = (string) $s->fetch($file);
echo "==== Final ====\n";
echo "$d\n==== Bye ====\n\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment