mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-04-02 01:52:10 +09:00
commit
3d16272d01
2 changed files with 312 additions and 16 deletions
|
|
@ -554,26 +554,132 @@ class TemplateHandler
|
|||
}
|
||||
else
|
||||
{
|
||||
$escape_option = $this->config->autoescape !== null ? 'auto' : 'noescape';
|
||||
if(preg_match('@^(.+)\\|((?:no)?escape)$@', $m[1], $mm))
|
||||
{
|
||||
$m[1] = $mm[1];
|
||||
$escape_option = $mm[2];
|
||||
}
|
||||
elseif($m[1] === '$content' && preg_match('@/layouts/.+/layout\.html$@', $this->file))
|
||||
// Get escape options.
|
||||
if($m[1] === '$content' && preg_match('@/layouts/.+/layout\.html$@', $this->file))
|
||||
{
|
||||
$escape_option = 'noescape';
|
||||
}
|
||||
$m[1] = self::_replaceVar($m[1]);
|
||||
switch($escape_option)
|
||||
else
|
||||
{
|
||||
case 'auto':
|
||||
return "<?php echo (\$this->config->autoescape === 'on' ? htmlspecialchars({$m[1]}, ENT_COMPAT, 'UTF-8', false) : {$m[1]}) ?>";
|
||||
case 'escape':
|
||||
return "<?php echo htmlspecialchars({$m[1]}, ENT_COMPAT, 'UTF-8', true) ?>";
|
||||
case 'noescape':
|
||||
return "<?php echo {$m[1]} ?>";
|
||||
$escape_option = $this->config->autoescape !== null ? 'auto' : 'noescape';
|
||||
}
|
||||
|
||||
// Separate filters from variable.
|
||||
if (preg_match('@^(.+?)(?<![|\s])((?:\|[a-z]{2}[a-z0-9_]+(?::.+)?)+)$@', $m[1], $mm))
|
||||
{
|
||||
$m[1] = $mm[1];
|
||||
$filters = array_map('trim', explode_with_escape('|', substr($mm[2], 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$filters = array();
|
||||
}
|
||||
|
||||
// Process the variable.
|
||||
$var = self::_replaceVar($m[1]);
|
||||
|
||||
// Apply filters.
|
||||
foreach ($filters as $filter)
|
||||
{
|
||||
// Separate filter option from the filter name.
|
||||
if (preg_match('/^([a-z0-9_-]+):(.+)$/', $filter, $matches))
|
||||
{
|
||||
$filter = $matches[1];
|
||||
$filter_option = $matches[2];
|
||||
if (!self::_isVar($filter_option) && !preg_match("/^'.*'$/", $filter_option) && !preg_match('/^".*"$/', $filter_option))
|
||||
{
|
||||
$filter_option = "'" . escape_sqstr($filter_option) . "'";
|
||||
}
|
||||
else
|
||||
{
|
||||
$filter_option = self::_replaceVar($filter_option);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$filter_option = null;
|
||||
}
|
||||
|
||||
// Apply each filter.
|
||||
switch ($filter)
|
||||
{
|
||||
case 'auto':
|
||||
case 'autoescape':
|
||||
case 'escape':
|
||||
case 'noescape':
|
||||
$escape_option = $filter;
|
||||
break;
|
||||
|
||||
case 'escapejs':
|
||||
$var = "escape_js({$var})";
|
||||
break;
|
||||
|
||||
case 'json':
|
||||
$var = "json_encode({$var})";
|
||||
break;
|
||||
|
||||
case 'strip':
|
||||
case 'strip_tags':
|
||||
$var = $filter_option ? "strip_tags({$var}, {$filter_option})" : "strip_tags({$var})";
|
||||
break;
|
||||
|
||||
case 'trim':
|
||||
$var = "trim({$var})";
|
||||
break;
|
||||
|
||||
case 'urlencode':
|
||||
$var = "rawurlencode({$var})";
|
||||
break;
|
||||
|
||||
case 'lower':
|
||||
$var = "strtolower({$var})";
|
||||
break;
|
||||
|
||||
case 'upper':
|
||||
$var = "strtoupper({$var})";
|
||||
break;
|
||||
|
||||
case 'nl2br':
|
||||
$var = $this->_applyEscapeOption($var, $escape_option);
|
||||
$var = "nl2br({$var})";
|
||||
$escape_option = 'noescape';
|
||||
break;
|
||||
|
||||
case 'join':
|
||||
$var = $filter_option ? "implode({$filter_option}, {$var})" : "implode(', ', {$var})";
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
$var = $filter_option ? "getDisplayDateTime(ztime({$var}), {$filter_option})" : "getDisplayDateTime(ztime({$var}), 'Y-m-d H:i:s')";
|
||||
break;
|
||||
|
||||
case 'format':
|
||||
case 'number_format':
|
||||
$var = $filter_option ? "number_format({$var}, {$filter_option})" : "number_format({$var})";
|
||||
break;
|
||||
|
||||
case 'link':
|
||||
$var = $this->_applyEscapeOption($var, $escape_option);
|
||||
if ($filter_option)
|
||||
{
|
||||
$filter_option = $this->_applyEscapeOption($filter_option, $escape_option);
|
||||
$var = "'<a href=\"' . {$filter_option} . '\">' . {$var} . '</a>'";
|
||||
}
|
||||
else
|
||||
{
|
||||
$var = "'<a href=\"' . {$var} . '\">' . {$var} . '</a>'";
|
||||
}
|
||||
$escape_option = 'noescape';
|
||||
break;
|
||||
|
||||
default:
|
||||
$filter = escape_sqstr($filter);
|
||||
$var = "'INVALID FILTER ({$filter})'";
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the escape option and return.
|
||||
return '<?php echo ' . $this->_applyEscapeOption($var, $escape_option) . ' ?>';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -773,6 +879,25 @@ class TemplateHandler
|
|||
return $m[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply escape option to an expression.
|
||||
*/
|
||||
private function _applyEscapeOption($str, $escape_option)
|
||||
{
|
||||
switch($escape_option)
|
||||
{
|
||||
case 'escape':
|
||||
return "htmlspecialchars({$str}, ENT_COMPAT, 'UTF-8', true)";
|
||||
case 'noescape':
|
||||
return "{$str}";
|
||||
case 'autoescape':
|
||||
return "htmlspecialchars({$str}, ENT_COMPAT, 'UTF-8', false)";
|
||||
case 'auto':
|
||||
default:
|
||||
return "(\$this->config->autoescape === 'on' ? htmlspecialchars({$str}, ENT_COMPAT, 'UTF-8', false) : {$str})";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* change relative path
|
||||
* @param string $path
|
||||
|
|
@ -810,9 +935,21 @@ class TemplateHandler
|
|||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string seems to contain a variable.
|
||||
*
|
||||
* @param string $str
|
||||
* @return bool
|
||||
*/
|
||||
private static function _isVar($str)
|
||||
{
|
||||
return preg_match('@(?<!::|\\\\|(?<!eval\()\')\$([a-z_][a-z0-9_]*)@i', $str) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* replace PHP variables of $ character
|
||||
* Replace PHP variables of $ character
|
||||
*
|
||||
* @param string $php
|
||||
* @return string $__Context->varname
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -300,6 +300,165 @@ class TemplateHandlerTest extends \Codeception\TestCase\Test
|
|||
array(
|
||||
'<span>{\RX_BASEDIR}</span>',
|
||||
'?><span><?php echo \RX_BASEDIR ?></span>'
|
||||
),
|
||||
// Rhymix autoescape
|
||||
array(
|
||||
'<config autoescape="on" />{$foo}',
|
||||
PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="off" />{$foo}',
|
||||
PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="on" />{$foo|auto}',
|
||||
PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="off" />{$foo|auto}',
|
||||
PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="on" />{$foo|autoescape}',
|
||||
PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="off" />{$foo|autoescape}',
|
||||
PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="on" />{$foo|escape}',
|
||||
PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', true) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="off" />{$foo|escape}',
|
||||
PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', true) ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="on" />{$foo|noescape}',
|
||||
PHP_EOL . '$this->config->autoescape = \'on\';' . "\n" . 'echo $__Context->foo ?>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="off" />{$foo|noescape}',
|
||||
PHP_EOL . '$this->config->autoescape = \'off\';' . "\n" . 'echo $__Context->foo ?>'
|
||||
),
|
||||
// Rhymix filters
|
||||
array(
|
||||
'<p>{$foo|escape}</p>',
|
||||
'?><p><?php echo htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', true) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|json}</p>',
|
||||
'?><p><?php echo json_encode($__Context->foo) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|urlencode}</p>',
|
||||
'?><p><?php echo rawurlencode($__Context->foo) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|lower|nl2br}</p>',
|
||||
'?><p><?php echo nl2br(strtolower($__Context->foo)) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|join:/|upper}</p>',
|
||||
'?><p><?php echo strtoupper(implode(\'/\', $__Context->foo)) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|join:\||upper}</p>',
|
||||
'?><p><?php echo strtoupper(implode(\'|\', $__Context->foo)) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|join:$separator}</p>',
|
||||
'?><p><?php echo implode($__Context->separator, $__Context->foo) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|strip}</p>',
|
||||
'?><p><?php echo strip_tags($__Context->foo) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|strip:<br>}</p>',
|
||||
'?><p><?php echo strip_tags($__Context->foo, \'<br>\') ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|strip:$mytags}</p>',
|
||||
'?><p><?php echo strip_tags($__Context->foo, $__Context->mytags) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|strip:myfunc($mytags)}</p>',
|
||||
'?><p><?php echo strip_tags($__Context->foo, myfunc($__Context->mytags)) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|trim|date}</p>',
|
||||
'?><p><?php echo getDisplayDateTime(ztime(trim($__Context->foo)), \'Y-m-d H:i:s\') ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|date:His}</p>',
|
||||
'?><p><?php echo getDisplayDateTime(ztime($__Context->foo), \'His\') ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|format:2}</p>',
|
||||
'?><p><?php echo number_format($__Context->foo, \'2\') ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|date:His}</p>',
|
||||
'?><p><?php echo getDisplayDateTime(ztime($__Context->foo), \'His\') ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|link}</p>',
|
||||
'?><p><?php echo \'<a href="\' . $__Context->foo . \'">\' . $__Context->foo . \'</a>\' ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|link:http://www.rhymix.org}</p>',
|
||||
'?><p><?php echo \'<a href="\' . \'http://www.rhymix.org\' . \'">\' . $__Context->foo . \'</a>\' ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|link:$url}</p>',
|
||||
'?><p><?php echo \'<a href="\' . $__Context->url . \'">\' . $__Context->foo . \'</a>\' ?></p>'
|
||||
),
|
||||
array(
|
||||
'<config autoescape="on" /><p>{$foo|link:$url}</p>',
|
||||
PHP_EOL . '$this->config->autoescape = \'on\'; ?><p><?php echo \'<a href="\' . ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->url, ENT_COMPAT, \'UTF-8\', false) : $__Context->url) . \'">\' . ($this->config->autoescape === \'on\' ? htmlspecialchars($__Context->foo, ENT_COMPAT, \'UTF-8\', false) : $__Context->foo) . \'</a>\' ?></p>'
|
||||
),
|
||||
// Rhymix filters (reject malformed filters)
|
||||
array(
|
||||
'<p>{$foo|dafuq}</p>',
|
||||
'?><p><?php echo \'INVALID FILTER (dafuq)\' ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|4}</p>',
|
||||
'?><p><?php echo $__Context->foo|4 ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|a+7|lower}</p>',
|
||||
'?><p><?php echo strtolower($__Context->foo|a+7) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|Filter}</p>',
|
||||
'?><p><?php echo $__Context->foo|Filter ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|filter++}</p>',
|
||||
'?><p><?php echo $__Context->foo|filter++ ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|filter:}</p>',
|
||||
'?><p><?php echo $__Context->foo|filter: ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo|$bar}</p>',
|
||||
'?><p><?php echo $__Context->foo|$__Context->bar ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo||bar}</p>',
|
||||
'?><p><?php echo $__Context->foo||bar ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{htmlspecialchars($var, ENT_COMPAT | ENT_HTML401)}</p>',
|
||||
'?><p><?php echo htmlspecialchars($__Context->var, ENT_COMPAT | ENT_HTML401) ?></p>'
|
||||
),
|
||||
array(
|
||||
'<p>{$foo | $bar}</p>',
|
||||
'?><p><?php echo $__Context->foo | $__Context->bar ?></p>'
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue