diff --git a/libs/sysplugins/smarty_internal_method_literals.php b/libs/sysplugins/smarty_internal_method_literals.php
new file mode 100644
index 00000000..6dd4e26d
--- /dev/null
+++ b/libs/sysplugins/smarty_internal_method_literals.php
@@ -0,0 +1,96 @@
+_getSmartyObj();
+ return (array)$smarty->literals;
+ }
+
+ /**
+ * Add literals
+ *
+ * @api Smarty::addLiterals()
+ *
+ * @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
+ * @param array|string $literals literal or list of literals
+ * to add
+ *
+ * @return \Smarty|\Smarty_Internal_Template
+ */
+ public function addLiterals(Smarty_Internal_TemplateBase $obj, $literals = null)
+ {
+ if (isset($literals)) {
+ $this->set($obj->_getSmartyObj(), (array)$literals);
+ }
+ return $obj;
+ }
+
+ /**
+ * Set literals
+ *
+ * @api Smarty::setLiterals()
+ *
+ * @param \Smarty_Internal_TemplateBase|\Smarty_Internal_Template|\Smarty $obj
+ * @param array|string $literals literal or list of literals
+ * to set
+ *
+ * @return \Smarty|\Smarty_Internal_Template
+ */
+ public function setLiterals(Smarty_Internal_TemplateBase $obj, $literals = null)
+ {
+ $smarty = $obj->_getSmartyObj();
+ $smarty->literals = array();
+ if (!empty($literals)) {
+ $this->set($smarty, (array)$literals);
+ }
+ return $obj;
+ }
+
+ /**
+ * common setter for literals for easier handling of duplicates the
+ * Smarty::$literals array gets filled with identical key values
+ *
+ * @param \Smarty $smarty
+ * @param array $literals
+ *
+ * @throws \SmartyException
+ */
+ private function set(Smarty $smarty, $literals)
+ {
+ $literals = array_combine($literals, $literals);
+ $error = isset($literals[ $smarty->left_delimiter ]) ? array($smarty->left_delimiter) : array();
+ $error = isset($literals[ $smarty->right_delimiter ]) ? $error[] = $smarty->right_delimiter : $error;
+ if (!empty($error)) {
+ throw new SmartyException('User defined literal(s) "' . $error .
+ '" may not be identical with left or right delimiter');
+ }
+ $smarty->literals = array_merge((array)$smarty->literals, (array)$literals);
+ }
+}
\ No newline at end of file
diff --git a/libs/sysplugins/smarty_internal_templatebase.php b/libs/sysplugins/smarty_internal_templatebase.php
index 1a5285ef..463c4b39 100644
--- a/libs/sysplugins/smarty_internal_templatebase.php
+++ b/libs/sysplugins/smarty_internal_templatebase.php
@@ -21,10 +21,12 @@
*
* @method Smarty_Internal_TemplateBase addAutoloadFilters(mixed $filters, string $type = null)
* @method Smarty_Internal_TemplateBase addDefaultModifier(mixed $modifiers)
+ * @method Smarty_Internal_TemplateBase addLiterals(mixed $literals)
* @method Smarty_Internal_TemplateBase createData(Smarty_Internal_Data $parent = null, string $name = null)
* @method array getAutoloadFilters(string $type = null)
* @method string getDebugTemplate()
* @method array getDefaultModifier()
+ * @method array getLiterals()
* @method array getTags(mixed $template = null)
* @method object getRegisteredObject(string $object_name)
* @method Smarty_Internal_TemplateBase registerCacheResource(string $name, Smarty_CacheResource $resource_handler)
@@ -36,6 +38,7 @@
* @method Smarty_Internal_TemplateBase setAutoloadFilters(mixed $filters, string $type = null)
* @method Smarty_Internal_TemplateBase setDebugTemplate(string $tpl_name)
* @method Smarty_Internal_TemplateBase setDefaultModifiers(mixed $modifiers)
+ * @method Smarty_Internal_TemplateBase setLiterals(mixed $literals)
* @method Smarty_Internal_TemplateBase unloadFilter(string $type, string $name)
* @method Smarty_Internal_TemplateBase unregisterCacheResource(string $name)
* @method Smarty_Internal_TemplateBase unregisterObject(string $object_name)
diff --git a/libs/sysplugins/smarty_internal_templatelexer.php b/libs/sysplugins/smarty_internal_templatelexer.php
index a6d0ec21..46e0f835 100644
--- a/libs/sysplugins/smarty_internal_templatelexer.php
+++ b/libs/sysplugins/smarty_internal_templatelexer.php
@@ -18,71 +18,83 @@
*/
class Smarty_Internal_Templatelexer
{
- const TEXT = 1;
- const TAG = 2;
- const TAGBODY = 3;
- const LITERAL = 4;
- const DOUBLEQUOTEDSTRING = 5;
/**
* Source
*
* @var string
*/
public $data;
+
/**
* Source length
*
* @var int
*/
public $dataLength = null;
+
/**
* byte counter
*
* @var int
*/
public $counter;
+
/**
* token number
*
* @var int
*/
public $token;
+
/**
* token value
*
* @var string
*/
public $value;
+
/**
* current line
*
* @var int
*/
public $line;
+
/**
* tag start line
*
* @var
*/
public $taglineno;
+
/**
* php code type
*
* @var string
*/
public $phpType = '';
+
/**
* escaped left delimiter
*
* @var string
*/
public $ldel = '';
+
+ /**
+ * escaped left delimiter with space
+ *
+ * @var string
+ */
+ public $ldel_q = '';
+
/**
* escaped left delimiter length
*
* @var int
*/
public $ldel_length = 0;
+
/**
* escaped right delimiter
*
@@ -90,112 +102,165 @@ class Smarty_Internal_Templatelexer
*/
public $rdel = '';
- /**
- * PHP start tag string
- *
- * @var string
- */
/**
* escaped right delimiter length
*
* @var int
*/
public $rdel_length = 0;
+
/**
* state number
*
* @var int
*/
public $state = 1;
+
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
+
/**
* compiler object
*
* @var Smarty_Internal_TemplateCompilerBase
*/
public $compiler = null;
+
/**
* trace file
*
* @var resource
*/
public $yyTraceFILE;
+
/**
* trace prompt
*
* @var string
*/
public $yyTracePrompt;
+
/**
* XML flag true while processing xml
*
* @var bool
*/
public $is_xml = false;
+
/**
* state names
*
* @var array
*/
public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',);
+
/**
* token names
*
* @var array
*/
public $smarty_token_names = array( // Text for parser error messages
- 'NOT' => '(!,not)', 'OPENP' => '(', 'CLOSEP' => ')', 'OPENB' => '[',
- 'CLOSEB' => ']', 'PTR' => '->', 'APTR' => '=>', 'EQUAL' => '=',
- 'NUMBER' => 'number', 'UNIMATH' => '+" , "-', 'MATH' => '*" , "/" , "%',
- 'INCDEC' => '++" , "--', 'SPACE' => ' ', 'DOLLAR' => '$',
- 'SEMICOLON' => ';', 'COLON' => ':', 'DOUBLECOLON' => '::', 'AT' => '@',
- 'HATCH' => '#', 'QUOTE' => '"', 'BACKTICK' => '`',
- 'VERT' => '"|" modifier', 'DOT' => '.', 'COMMA' => '","',
- 'QMARK' => '"?"', 'ID' => 'id, name', 'TEXT' => 'text',
- 'LDELSLASH' => '{/..} closing tag', 'LDEL' => '{...} Smarty tag',
- 'COMMENT' => 'comment', 'AS' => 'as', 'TO' => 'to',
- 'PHP' => '" '"<", "==" ... logical operator',
- 'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition',
- 'SCOND' => '"is even" ... if condition',);
+ 'NOT' => '(!,not)',
+ 'OPENP' => '(',
+ 'CLOSEP' => ')',
+ 'OPENB' => '[',
+ 'CLOSEB' => ']',
+ 'PTR' => '->',
+ 'APTR' => '=>',
+ 'EQUAL' => '=',
+ 'NUMBER' => 'number',
+ 'UNIMATH' => '+" , "-',
+ 'MATH' => '*" , "/" , "%',
+ 'INCDEC' => '++" , "--',
+ 'SPACE' => ' ',
+ 'DOLLAR' => '$',
+ 'SEMICOLON' => ';',
+ 'COLON' => ':',
+ 'DOUBLECOLON' => '::',
+ 'AT' => '@',
+ 'HATCH' => '#',
+ 'QUOTE' => '"',
+ 'BACKTICK' => '`',
+ 'VERT' => '"|" modifier',
+ 'DOT' => '.',
+ 'COMMA' => '","',
+ 'QMARK' => '"?"',
+ 'ID' => 'id, name',
+ 'TEXT' => 'text',
+ 'LDELSLASH' => '{/..} closing tag',
+ 'LDEL' => '{...} Smarty tag',
+ 'COMMENT' => 'comment',
+ 'AS' => 'as',
+ 'TO' => 'to',
+ 'PHP' => '" '"<", "==" ... logical operator',
+ 'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition',
+ 'SCOND' => '"is even" ... if condition',
+ );
+
+ /**
+ * preg string of user defined litereals
+ *
+ * @var string
+ */
+ public $literals = '';
+
/**
* literal tag nesting level
*
* @var int
*/
private $literal_cnt = 0;
+
/**
- * storage for assembled token patterns
+ * preg token pattern for state TEXT
*
* @var string
*/
private $yy_global_pattern1 = null;
+
+ /**
+ * preg token pattern for state TAG
+ *
+ * @var string
+ */
private $yy_global_pattern2 = null;
- /*
- * Check if this tag is autoliteral
- */
+ /**
+ * preg token pattern for state TAGBODY
+ *
+ * @var string
+ */
private $yy_global_pattern3 = null;
+
+ /**
+ * preg token pattern for state LITERAL
+ *
+ * @var string
+ */
private $yy_global_pattern4 = null;
+
+ /**
+ * preg token pattern for state DOUBLEQUOTEDSTRING
+ *
+ * @var null
+ */
private $yy_global_pattern5 = null;
- private $_yy_state = 1;
- private $_yy_stack = array();
/**
* constructor
*
- * @param string $data template source
+ * @param string $source template source
* @param Smarty_Internal_TemplateCompilerBase $compiler
*/
- function __construct($data, Smarty_Internal_TemplateCompilerBase $compiler)
+ function __construct($source, Smarty_Internal_TemplateCompilerBase $compiler)
{
- $this->data = $data;
- $this->dataLength = strlen($data);
+ $this->data = $source;
+ $this->dataLength = strlen($this->data);
$this->counter = 0;
if (preg_match('/^\xEF\xBB\xBF/i', $this->data, $match)) {
$this->counter += strlen($match[0]);
@@ -203,52 +268,129 @@ class Smarty_Internal_Templatelexer
$this->line = 1;
$this->smarty = $compiler->smarty;
$this->compiler = $compiler;
- $this->pldel = preg_quote($this->smarty->left_delimiter, '/');
- $this->ldel = $this->pldel . ($this->smarty->auto_literal ? '(?!\\s+)' : '\\s*');
+ $this->ldel = preg_quote($this->smarty->left_delimiter, '/') . ($this->smarty->auto_literal ? '' : '\\s*');
$this->ldel_length = strlen($this->smarty->left_delimiter);
$this->rdel = preg_quote($this->smarty->right_delimiter, '/');
$this->rdel_length = strlen($this->smarty->right_delimiter);
$this->smarty_token_names['LDEL'] = $this->smarty->left_delimiter;
$this->smarty_token_names['RDEL'] = $this->smarty->right_delimiter;
+ $literals = $this->smarty->getLiterals();
+ if (!empty($literals)) {
+ foreach ($literals as $key => $literal) {
+ $literals[$key] = preg_quote($literal, '/');
+ }
+ }
+ if ($this->smarty->auto_literal) {
+ $literals[] = $this->ldel . '{1,}\\s+';
+ }
+ if (!empty($literals)) {
+ $this->literals = implode('|', $literals);
+ } else {
+ $this->literals = preg_quote('^$', '/');
+ }
}
+ /**
+ * open lexer/parser trace file
+ *
+ */
public function PrintTrace()
{
$this->yyTraceFILE = fopen('php://output', 'w');
$this->yyTracePrompt = '
';
}
+ /**
+ * replace placeholders with runtime preg code
+ *
+ * @param string $input
+ *
+ * @return string
+ */
+ public function replace($input)
+ {
+ return str_replace(array('SMARTYldel', 'SMARTYliteral', 'SMARTYrdel'),
+ array($this->ldel, $this->literals, $this->rdel),
+ $input);
+ }
+
+ /**
+ * check if current value is an autoliteral left delimiter
+ *
+ * @return bool
+ */
public function isAutoLiteral()
{
return $this->smarty->auto_literal && isset($this->value[ $this->ldel_length ]) ?
strpos(" \n\t\r", $this->value[ $this->ldel_length ]) !== false : false;
}
-public function yylex1()
+
+ private $_yy_state = 1;
+ private $_yy_stack = array();
+
+ public function yylex()
+ {
+ return $this->{'yylex' . $this->_yy_state}();
+ }
+
+ public function yypushstate($state)
+ {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sState push %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
+ }
+ array_push($this->_yy_stack, $this->_yy_state);
+ $this->_yy_state = $state;
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%snew State %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
+ }
+ }
+
+ public function yypopstate()
+ {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sState pop %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
+ }
+ $this->_yy_state = array_pop($this->_yy_stack);
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%snew State %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
+ }
+
+ }
+
+ public function yybegin($state)
+ {
+ $this->_yy_state = $state;
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sState set %s\n", $this->yyTracePrompt, isset($this->state_name[$this->_yy_state]) ? $this->state_name[$this->_yy_state] : $this->_yy_state);
+ }
+ }
+
+
+
+ public function yylex1()
{
if (!isset($this->yy_global_pattern1)) {
- $this->yy_global_pattern1 =
- $this->replace("/\G([{][}])|\G(SMARTYldel[*])|\G((SMARTYldelphp([ ].*?)?SMARTYrdel)|(SMARTYldel[\/]phpSMARTYrdel))|\G(SMARTYrawldel{2,})|\G(SMARTYldelliteral\\s*SMARTYrdel)|\G(SMARTYldel[\/]literal\\s*SMARTYrdel)|\G(SMARTYldel)|\G((<[?]((php\\s+|=)|\\s+))|(<[%])|(<[?]xml\\s+)|(