` tag (arrays are cycled) |
+| td\_attr | No | Attributes for `` tag (arrays are cycled) |
+| trailpad | No | Value to pad the trailing cells on last row with (if any) (defaults to ' ') |
+| hdir | No | Direction of each row to be rendered. possible values: *right* (left-to-right), and *left* (right-to-left) (defaults to 'right') |
+| vdir | No | Direction of each column to be rendered. possible values: *down* (top-to-bottom), *up* (bottom-to-top) (defaults to 'down') |
+
+- The `cols` attribute determines how many columns will be in the
+ table.
+
+- The `table_attr`, `tr_attr` and `td_attr` values determine the
+ attributes given to the ``, `` and `` tags.
+
+- If `tr_attr` or `td_attr` are arrays, they will be cycled through.
+
+- `trailpad` is the value put into the trailing cells on the last
+ table row if there are any present.
+
+## Examples
+
+```php
+assign( 'data', array(1,2,3,4,5,6,7,8,9) );
+$smarty->assign( 'tr', array('bgcolor="#eeeeee"','bgcolor="#dddddd"') );
+$smarty->display('index.tpl');
+```
+
+The variables assigned from php could be displayed as these three
+examples demonstrate. Each example shows the template followed by
+output.
+
+** Example 1 **
+```smarty
+{html_table loop=$data}
+```
+```html
+
+```
+
+** Example 2 **
+```smarty
+{html_table loop=$data cols=4 table_attr='border="0"'}
+```
+```html
+
+```
+
+** Example 3 **
+```smarty
+{html_table loop=$data cols="first,second,third,fourth" tr_attr=$tr}
+```
+```html
+
+
+
+ first second third fourth
+
+
+
+ 1 2 3 4
+ 5 6 7 8
+ 9
+
+
+```
+
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-mailto.md b/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-mailto.md
new file mode 100644
index 0000000..c32c238
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-mailto.md
@@ -0,0 +1,61 @@
+# {mailto}
+
+`{mailto}` automates the creation of a `mailto:` anchor links and
+optionally encodes them. Encoding emails makes it more difficult for web
+spiders to lift email addresses off of a site.
+
+## Attributes
+
+| Attribute Name | Required | Description |
+|----------------|----------|-----------------------------------------------------------------------------------------------|
+| address | Yes | The e-mail address |
+| text | No | The text to display, default is the e-mail address |
+| encode | No | How to encode the e-mail. Can be one of `none`, `hex`, `javascript` or `javascript_charcode`. |
+| cc | No | Email addresses to carbon copy, separate entries by a comma. |
+| bcc | No | Email addresses to blind carbon copy, separate entries by a comma |
+| subject | No | Email subject |
+| newsgroups | No | Newsgroups to post to, separate entries by a comma. |
+| followupto | No | Addresses to follow up to, separate entries by a comma. |
+| extra | No | Any extra information you want passed to the link, such as style sheet classes |
+
+> **Note**
+>
+> Javascript is probably the most thorough form of encoding, although
+> you can use hex encoding too.
+
+
+## Examples
+
+```smarty
+{mailto address="me@example.com"}
+me@example.com
+
+{mailto address="me@example.com" text="send me some mail"}
+send me some mail
+
+{mailto address="me@example.com" encode="javascript"}
+
+
+{mailto address="me@example.com" encode="hex"}
+m&..snipped...#x6f;m
+
+{mailto address="me@example.com" subject="Hello to you!"}
+me@example.com
+
+{mailto address="me@example.com" cc="you@example.com,they@example.com"}
+me@example.com
+
+{mailto address="me@example.com" extra='class="email"'}
+me@example.com
+
+{mailto address="me@example.com" encode="javascript_charcode"}
+
+```
+
+See also [`escape`](../language-modifiers/language-modifier-escape.md),
+[`{textformat}`](../language-custom-functions/language-function-textformat.md) and [obfuscating email
+addresses](../../appendixes/tips.md#obfuscating-e-mail-addresses).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-math.md b/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-math.md
new file mode 100644
index 0000000..7b34fcc
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-math.md
@@ -0,0 +1,99 @@
+# {math}
+
+`{math}` allows the template designer to do math equations in the
+template.
+
+## Attributes
+
+| Attribute Name | Required | Description |
+|----------------|----------|--------------------------------------------------|
+| equation | Yes | The equation to execute |
+| format | No | The format of the result (sprintf) |
+| var | Yes | Equation variable value |
+| assign | No | Template variable the output will be assigned to |
+| \[var \...\] | Yes | Equation variable value |
+
+- Any numeric template variables may be used in the equations, and the
+ result is printed in place of the tag.
+
+- The variables used in the equation are passed as parameters, which
+ can be template variables or static values.
+
+- +, -, /, \*, abs, ceil, cos, exp, floor, log, log10, max, min, pi,
+ pow, rand, round, sin, sqrt, srans and tan are all valid operators.
+ Check the PHP documentation for further information on these
+ [math](https://www.php.net/eval) functions.
+
+- If you supply the `assign` attribute, the output of the `{math}`
+ function will be assigned to this template variable instead of being
+ output to the template.
+
+> **Note**
+>
+> `{math}` is an expensive function in performance due to its use of the
+> php [`eval()`](https://www.php.net/eval) function. Doing the math in PHP
+> is much more efficient, so whenever possible do the math calculations
+> in the script and [`assign()`](../../programmers/api-functions/api-assign.md) the results to the
+> template. Definitely avoid repetitive `{math}` function calls, eg
+> within [`{section}`](../language-builtin-functions/language-function-section.md) loops.
+
+## Examples
+
+**Example 1**
+```smarty
+
+{* $height=4, $width=5 *}
+
+{math equation="x + y" x=$height y=$width}
+```
+
+The above example will output:
+
+```
+9
+```
+
+
+**Example 2**
+
+```smarty
+{* $row_height = 10, $row_width = 20, #col_div# = 2, assigned in template *}
+
+{math equation="height * width / division"
+ height=$row_height
+ width=$row_width
+ division=#col_div#}
+```
+
+The above example will output:
+
+```
+100
+```
+
+**Example 3**
+
+```smarty
+{* you can use parenthesis *}
+
+{math equation="(( x + y ) / z )" x=2 y=10 z=2}
+```
+
+The above example will output:
+
+```
+6
+```
+
+**Example 4**
+
+```smarty
+{* you can supply a format parameter in sprintf format *}
+
+{math equation="x + y" x=4.4444 y=5.0000 format="%.2f"}
+```
+
+The above example will output:
+```
+9.44
+```
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-textformat.md b/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-textformat.md
new file mode 100644
index 0000000..cb2a8d7
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-custom-functions/language-function-textformat.md
@@ -0,0 +1,182 @@
+# {textformat}
+
+`{textformat}` is a block tag used to
+format text. It basically cleans up spaces and special characters, and
+formats paragraphs by wrapping at a boundary and indenting lines.
+
+You can set the parameters explicitly, or use a preset style. Currently,
+"email" is the only available style.
+
+## Attributes
+
+| Attribute Name | Default | Description |
+|----------------|------------------|----------------------------------------------------------------------------------------|
+| style | *n/a* | Preset style |
+| indent | *0* | The number of chars to indent every line |
+| indent\_first | *0* | The number of chars to indent the first line |
+| indent\_char | *(single space)* | The character (or string of chars) to indent with |
+| wrap | *80* | How many characters to wrap each line to |
+| wrap\_char | *\\n* | The character (or string of chars) to break each line with |
+| wrap\_cut | *FALSE* | If TRUE, wrap will break the line at the exact character instead of at a word boundary |
+| assign | *n/a* | The template variable the output will be assigned to |
+
+## Examples
+
+```smarty
+{textformat wrap=40}
+
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+
+This is bar.
+
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+
+{/textformat}
+```
+
+The above example will output:
+
+```
+This is foo. This is foo. This is foo.
+This is foo. This is foo. This is foo.
+
+This is bar.
+
+bar foo bar foo foo. bar foo bar foo
+foo. bar foo bar foo foo. bar foo bar
+foo foo. bar foo bar foo foo. bar foo
+bar foo foo. bar foo bar foo foo.
+```
+
+```smarty
+{textformat wrap=40 indent=4}
+
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+
+This is bar.
+
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+
+{/textformat}
+```
+
+The above example will output:
+
+```
+ This is foo. This is foo. This is
+ foo. This is foo. This is foo. This
+ is foo.
+
+ This is bar.
+
+ bar foo bar foo foo. bar foo bar foo
+ foo. bar foo bar foo foo. bar foo
+ bar foo foo. bar foo bar foo foo.
+ bar foo bar foo foo. bar foo bar
+ foo foo.
+```
+
+
+```smarty
+{textformat wrap=40 indent=4 indent_first=4}
+
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+
+This is bar.
+
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+
+{/textformat}
+```
+
+The above example will output:
+
+
+```
+ This is foo. This is foo. This
+ is foo. This is foo. This is foo.
+ This is foo.
+
+ This is bar.
+
+ bar foo bar foo foo. bar foo bar
+ foo foo. bar foo bar foo foo. bar
+ foo bar foo foo. bar foo bar foo
+ foo. bar foo bar foo foo. bar foo
+ bar foo foo.
+```
+
+
+```smarty
+{textformat style="email"}
+
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+This is foo.
+
+This is bar.
+
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+bar foo bar foo foo.
+
+{/textformat}
+```
+
+The above example will output:
+
+
+```
+This is foo. This is foo. This is foo. This is foo. This is foo. This is
+foo.
+
+This is bar.
+
+bar foo bar foo foo. bar foo bar foo foo. bar foo bar foo foo. bar foo
+bar foo foo. bar foo bar foo foo. bar foo bar foo foo. bar foo bar foo
+foo.
+```
+
+
+See also [`{strip}`](../language-builtin-functions/language-function-strip.md) and
+[`wordwrap`](../language-modifiers/language-modifier-wordwrap.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/index.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/index.md
new file mode 100644
index 0000000..3f52c2e
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/index.md
@@ -0,0 +1,104 @@
+# Variable Modifiers
+
+Variable modifiers can be applied to
+[variables](../language-variables/index.md), [custom tags](../language-custom-functions/index.md)
+or strings. To apply a modifier,
+specify the value followed by a `|` (pipe) and the modifier name. A
+modifier may accept additional parameters that affect its behavior.
+These parameters follow the modifier name and are separated by a `:`
+(colon).
+
+Modifiers can be applied to any type of variables, including arrays
+and objects.
+
+## Examples
+
+```smarty
+{* apply modifier to a variable *}
+{$title|upper}
+
+{* modifier with parameters *}
+{$title|truncate:40:"..."}
+
+{* apply modifier to a function parameter *}
+{html_table loop=$myvar|upper}
+
+{* with parameters *}
+{html_table loop=$myvar|truncate:40:"..."}
+
+{* apply modifier to literal string *}
+{"foobar"|upper}
+
+{* using date_format to format the current date *}
+{$smarty.now|date_format:"%Y/%m/%d"}
+
+{* apply modifier to a custom function *}
+{mailto|upper address="smarty@example.com"}
+
+{* using php's str_repeat *}
+{"="|str_repeat:80}
+
+{* php's count *}
+{$myArray|@count}
+
+{* this will uppercase the whole array *}
+
+{html_options output=$my_array|upper}
+
+```
+
+## Combining Modifiers
+
+You can apply any number of modifiers to a variable. They will be
+applied in the order they are combined, from left to right. They must be
+separated with a `|` (pipe) character.
+
+```php
+assign('articleTitle', 'Smokers are Productive, but Death Cuts Efficiency.');
+```
+
+where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|upper|spacify}
+{$articleTitle|lower|spacify|truncate}
+{$articleTitle|lower|truncate:30|spacify}
+{$articleTitle|lower|spacify|truncate:30:". . ."}
+```
+
+
+The above example will output:
+
+```
+Smokers are Productive, but Death Cuts Efficiency.
+S M O K E R S A R ....snip.... H C U T S E F F I C I E N C Y .
+s m o k e r s a r ....snip.... b u t d e a t h c u t s...
+s m o k e r s a r e p r o d u c t i v e , b u t . . .
+s m o k e r s a r e p. . .
+```
+
+## Using modifiers in expressions
+
+Modifiers can also be used in expressions. For example, you can use the [isset modifier](./language-modifier-isset.md)
+to test if a variable holds a value different from null.
+
+```smarty
+{if $varA|isset}
+ variable A is set
+{/if}
+```
+
+You can also use modifiers in expressions in a PHP-style syntax:
+
+```smarty
+{if isset($varA)}
+ variable A is set
+{/if}
+```
+
+See also [`registerPlugin()`](../../programmers/api-functions/api-register-plugin.md), [combining
+modifiers](../language-combining-modifiers.md). and [extending smarty with
+plugins](../../api/extending/introduction.md)
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-capitalize.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-capitalize.md
new file mode 100644
index 0000000..0368c7b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-capitalize.md
@@ -0,0 +1,49 @@
+# capitalize
+
+This is used to capitalize the first letter of all words in a variable.
+This is similar to the PHP [`ucwords()`](https://www.php.net/ucwords)
+function.
+
+## Basic usage
+```smarty
+{$myVar|capitalize}
+```
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|---------|----------|-------------------------------------------------------------------------------------------------------|
+| 1 | boolean | No | This determines whether or not words with digits will be uppercased |
+| 2 | boolean | No | This determines whether or not Capital letters within words should be lowercased, e.g. "aAa" to "Aaa" |
+
+
+## Examples
+
+```php
+assign('articleTitle', 'next x-men film, x3, delayed.');
+
+```
+
+
+Where the template is:
+
+```smarty
+ {$articleTitle}
+ {$articleTitle|capitalize}
+ {$articleTitle|capitalize:true}
+```
+
+
+Will output:
+
+```
+ next x-men film, x3, delayed.
+ Next X-Men Film, x3, Delayed.
+ Next X-Men Film, X3, Delayed.
+```
+
+
+See also [`lower`](language-modifier-lower.md) and
+[`upper`](language-modifier-upper.md)
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-cat.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-cat.md
new file mode 100644
index 0000000..97dda4b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-cat.md
@@ -0,0 +1,36 @@
+# cat
+
+This value is concatenated to the given variable.
+
+## Basic usage
+```smarty
+{$myVar|cat:' units'}
+```
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|--------|----------|--------------------------------------------------|
+| 1 | string | No | This value to concatenate to the given variable. |
+
+## Examples
+
+```php
+assign('articleTitle', "Psychics predict world didn't end");
+
+```
+
+Where template is:
+
+```smarty
+ {$articleTitle|cat:' yesterday.'}
+```
+
+Will output:
+
+```
+ Psychics predict world didn't end yesterday.
+```
+
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-characters.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-characters.md
new file mode 100644
index 0000000..8fc37d7
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-characters.md
@@ -0,0 +1,43 @@
+# count_characters
+
+This is used to count the number of characters in a variable.
+
+## Basic usage
+```smarty
+{$myVar|count_characters}
+```
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|---------|----------|------------------------------------------------------------------------|
+| 1 | boolean | No | This determines whether to include whitespace characters in the count. |
+
+## Examples
+
+```php
+assign('articleTitle', 'Cold Wave Linked to Temperatures.');
+
+```
+
+Where template is:
+
+```smarty
+ {$articleTitle}
+ {$articleTitle|count_characters}
+ {$articleTitle|count_characters:true}
+```
+
+Will output:
+
+```
+ Cold Wave Linked to Temperatures.
+ 29
+ 33
+```
+
+See also [`count_words`](language-modifier-count-words.md),
+[`count_sentences`](language-modifier-count-sentences.md) and
+[`count_paragraphs`](language-modifier-count-paragraphs.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-paragraphs.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-paragraphs.md
new file mode 100644
index 0000000..060cb98
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-paragraphs.md
@@ -0,0 +1,41 @@
+# count_paragraphs
+
+This is used to count the number of paragraphs in a variable.
+
+## Basic usage
+```smarty
+{$myVar|count_paragraphs}
+```
+
+## Examples
+
+```php
+assign('articleTitle',
+ "War Dims Hope for Peace. Child's Death Ruins Couple's Holiday.\n\n
+ Man is Fatally Slain. Death Causes Loneliness, Feeling of Isolation."
+ );
+
+```
+
+Where template is:
+
+```smarty
+ {$articleTitle}
+ {$articleTitle|count_paragraphs}
+```
+
+
+Will output:
+
+```
+ War Dims Hope for Peace. Child's Death Ruins Couple's Holiday.
+
+ Man is Fatally Slain. Death Causes Loneliness, Feeling of Isolation.
+ 2
+```
+
+See also [`count_characters`](language-modifier-count-characters.md),
+[`count_sentences`](language-modifier-count-sentences.md) and
+[`count_words`](language-modifier-count-words.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-sentences.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-sentences.md
new file mode 100644
index 0000000..dd2f69c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-sentences.md
@@ -0,0 +1,39 @@
+# count_sentences
+
+This is used to count the number of sentences in a variable. A sentence
+being delimited by a dot, question- or exclamation-mark (.?!).
+
+## Basic usage
+```smarty
+{$myVar|count_sentences}
+```
+
+## Examples
+
+```php
+assign('articleTitle',
+ 'Two Soviet Ships Collide - One Dies.
+ Enraged Cow Injures Farmer with Axe.'
+ );
+
+```
+
+Where template is:
+
+```smarty
+ {$articleTitle}
+ {$articleTitle|count_sentences}
+```
+
+Will output:
+
+```
+ Two Soviet Ships Collide - One Dies. Enraged Cow Injures Farmer with Axe.
+ 2
+```
+
+See also [`count_characters`](language-modifier-count-characters.md),
+[`count_paragraphs`](language-modifier-count-paragraphs.md) and
+[`count_words`](language-modifier-count-words.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-words.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-words.md
new file mode 100644
index 0000000..1ab0d1d
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count-words.md
@@ -0,0 +1,35 @@
+# count_words
+
+This is used to count the number of words in a variable.
+
+## Basic usage
+```smarty
+{$myVar|count_words}
+```
+
+## Examples
+
+```php
+assign('articleTitle', 'Dealers Will Hear Car Talk at Noon.');
+
+```
+
+Where template is:
+
+```smarty
+ {$articleTitle}
+ {$articleTitle|count_words}
+```
+
+This will output:
+
+```
+ Dealers Will Hear Car Talk at Noon.
+ 7
+```
+
+See also [`count_characters`](language-modifier-count-characters.md),
+[`count_paragraphs`](language-modifier-count-paragraphs.md) and
+[`count_sentences`](language-modifier-count-sentences.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count.md
new file mode 100644
index 0000000..36436a3
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-count.md
@@ -0,0 +1,21 @@
+# count
+
+Returns the number of elements in an array (or Countable object). Will return 0 for null.
+Returns 1 for any other type (such as a string).
+
+If the optional mode parameter is set to 1, count() will recursively count the array.
+This is particularly useful for counting all the elements of a multidimensional array.
+
+## Basic usage
+```smarty
+{if $myVar|count > 3}4 or more{/if}
+{if count($myVar) > 3}4 or more{/if}
+```
+
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|--------------------------------------------------------|
+| 1 | int | No | If set to 1, count() will recursively count the array. |
+
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-date-format.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-date-format.md
new file mode 100644
index 0000000..620d085
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-date-format.md
@@ -0,0 +1,145 @@
+# date_format
+
+This formats a date and time into the given
+[`strftime()`](https://www.php.net/strftime) format. Dates can be passed to
+Smarty as unix [timestamps](https://www.php.net/function.time), [DateTime
+objects](https://www.php.net/class.DateTime), mysql timestamps or any string
+made up of month day year, parsable by php\'s
+[`strtotime()`](https://www.php.net/strtotime). Designers can then use
+`date_format` to have complete control of the formatting of the date. If
+the date passed to `date_format` is empty and a second parameter is
+passed, that will be used as the date to format.
+
+## Basic usage
+```smarty
+{$myVar|date_format:"%Y-%m-%d"}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Default | Description |
+|--------------------|--------|----------|-----------|-------------------------------------------------|
+| 1 | string | No | %b %e, %Y | This is the format for the outputted date. |
+| 2 | string | No | n/a | This is the default date if the input is empty. |
+
+> **Note**
+>
+> Since Smarty-2.6.10 numeric values passed to `date_format` are
+> *always* (except for mysql timestamps, see below) interpreted as a
+> unix timestamp.
+>
+> Before Smarty-2.6.10 numeric strings that where also parsable by
+> `strtotime()` in php (like `YYYYMMDD`) where sometimes (depending on
+> the underlying implementation of `strtotime()`) interpreted as date
+> strings and NOT as timestamps.
+>
+> The only exception are mysql timestamps: They are also numeric only
+> and 14 characters long (`YYYYMMDDHHMMSS`), mysql timestamps have
+> precedence over unix timestamps.
+
+> **Note**
+>
+> `date_format` is essentially a wrapper to PHP's
+> [`strftime()`](https://www.php.net/strftime) function. You may have more
+> or less conversion specifiers available depending on your system's
+> [`strftime()`](https://www.php.net/strftime) function where PHP was
+> compiled. Check your system\'s manpage for a full list of valid
+> specifiers. However, a few of the specifiers are emulated on Windows.
+> These are: %D, %e, %h, %l, %n, %r, %R, %t, %T.
+
+## Examples
+
+```php
+assign('config', $config);
+$smarty->assign('yesterday', strtotime('-1 day'));
+
+```
+
+This template uses [`$smarty.now`](../language-variables/language-variables-smarty.md#smartynow-languagevariablessmartynow) to
+get the current time:
+
+```smarty
+{$smarty.now|date_format}
+{$smarty.now|date_format:"%D"}
+{$smarty.now|date_format:$config.date}
+{$yesterday|date_format}
+{$yesterday|date_format:"%A, %B %e, %Y"}
+{$yesterday|date_format:$config.time}
+```
+
+This above will output:
+
+```
+Jan 1, 2022
+01/01/22
+02:33 pm
+Dec 31, 2021
+Monday, December 1, 2021
+14:33:00
+```
+
+## Conversion specifiers
+
+`date_format` conversion specifiers:
+
+- %a - abbreviated weekday name according to the current locale
+- %A - full weekday name according to the current locale
+- %b - abbreviated month name according to the current locale
+- %B - full month name according to the current locale
+- %c - preferred date and time representation for the current locale
+- %C - century number (the year divided by 100 and truncated to an
+ integer, range 00 to 99)
+- %d - day of the month as a decimal number (range 01 to 31)
+- %D - same as %m/%d/%y
+- %e - day of the month as a decimal number, a single digit is
+ preceded by a space (range 1 to 31)
+- %g - Week-based year within century \[00,99\]
+- %G - Week-based year, including the century \[0000,9999\]
+- %h - same as %b
+- %H - hour as a decimal number using a 24-hour clock (range 00
+ to 23)
+- %I - hour as a decimal number using a 12-hour clock (range 01
+ to 12)
+- %j - day of the year as a decimal number (range 001 to 366)
+- %k - Hour (24-hour clock) single digits are preceded by a blank.
+ (range 0 to 23)
+- %l - hour as a decimal number using a 12-hour clock, single digits
+ preceded by a space (range 1 to 12)
+- %m - month as a decimal number (range 01 to 12)
+- %M - minute as a decimal number
+- %n - newline character
+- %p - either 'am' or 'pm' according to the given time value, or
+ the corresponding strings for the current locale
+- %r - time in a.m. and p.m. notation
+- %R - time in 24 hour notation
+- %S - second as a decimal number
+- %t - tab character
+- %T - current time, equal to %H:%M:%S
+- %u - weekday as a decimal number \[1,7\], with 1 representing
+ Monday
+- %U - week number of the current year as a decimal number, starting
+ with the first Sunday as the first day of the first week
+- %V - The ISO 8601:1988 week number of the current year as a decimal
+ number, range 01 to 53, where week 1 is the first week that has at
+ least 4 days in the current year, and with Monday as the first day
+ of the week.
+- %w - day of the week as a decimal, Sunday being 0
+- %W - week number of the current year as a decimal number, starting
+ with the first Monday as the first day of the first week
+- %x - preferred date representation for the current locale without
+ the time
+- %X - preferred time representation for the current locale without
+ the date
+- %y - year as a decimal number without a century (range 00 to 99)
+- %Y - year as a decimal number including the century
+- %Z - time zone or name or abbreviation
+- %% - a literal '%' character
+
+See also [`$smarty.now`](../language-variables/language-variables-smarty.md#smartynow-languagevariablessmartynow),
+[`strftime()`](https://www.php.net/strftime),
+[`{html_select_date}`](../language-custom-functions/language-function-html-select-date.md) and the
+[date tips](../../appendixes/tips.md#dates) page.
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-debug-print-var.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-debug-print-var.md
new file mode 100644
index 0000000..ce3f86a
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-debug-print-var.md
@@ -0,0 +1,26 @@
+# debug_print_var
+
+
+
+Returns the value of the given variable in a human-readable format in HTML.
+Used in the [debug console](../chapter-debugging-console.md), but you can also use it in your template
+while developing to see what is going on under the hood.
+
+> **Note**
+>
+> Use for debugging only! Since you may accidentally reveal sensitive information or introduce vulnerabilities such as XSS using this
+method never use it in production.
+
+## Basic usage
+```smarty
+{$myVar|debug_print_var}
+```
+
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------|
+| 1 | int | No | maximum recursion depth if $var is an array or object (defaults to 10) |
+| 2 | int | No | maximum string length if $var is a string (defaults to 40) |
+
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-default.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-default.md
new file mode 100644
index 0000000..b8697a0
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-default.md
@@ -0,0 +1,45 @@
+# default
+
+This is used to set a default value for a variable. If the variable is
+unset or an empty string, the given default value is printed instead.
+Default takes the one argument.
+
+## Basic usage
+```smarty
+{$myVar|default:"(none)"}
+```
+
+## Parameters
+
+| Parameter | Type | Required | Default | Description |
+|-----------|--------|----------|---------|---------------------------------------------------------------|
+| 1 | string | No | *empty* | This is the default value to output if the variable is empty. |
+
+## Examples
+
+```php
+assign('articleTitle', 'Dealers Will Hear Car Talk at Noon.');
+ $smarty->assign('email', '');
+
+```
+
+Where template is:
+
+```smarty
+{$articleTitle|default:'no title'}
+{$myTitle|default:'no title'}
+{$email|default:'No email address available'}
+```
+
+Will output:
+
+```
+Dealers Will Hear Car Talk at Noon.
+no title
+No email address available
+```
+
+See also the [default variable handling](../../appendixes/tips.md#default-variable-handling) and
+the [blank variable handling](../../appendixes/tips.md#blank-variable-handling) pages.
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-escape.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-escape.md
new file mode 100644
index 0000000..18c98f1
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-escape.md
@@ -0,0 +1,78 @@
+# escape
+
+`escape` is used to encode or escape a variable to `html`, `url`,
+`single quotes`, `hex`, `hexentity`, `javascript` and `mail`. By default
+its `html`.
+
+## Basic usage
+```smarty
+{$myVar|escape}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Possible Values | Default | Description |
+|--------------------|---------|----------|----------------------------------------------------------------------------------------------------------------|---------|--------------------------------------------------------------------------------------|
+| 1 | string | No | `html`, `htmlall`, `url`, `urlpathinfo`, `quotes`, `hex`, `hexentity`, `javascript`, `mail` | `html` | This is the escape format to use. |
+| 2 | string | No | `ISO-8859-1`, `UTF-8`, and any character set supported by [`htmlentities()`](https://www.php.net/htmlentities) | `UTF-8` | The character set encoding passed to htmlentities() et. al. |
+| 3 | boolean | No | FALSE | TRUE | Double encode entities from & to & (applies to `html` and `htmlall` only) |
+
+
+## Examples
+
+```php
+assign('articleTitle',
+ "'Stiff Opposition Expected to Casketless Funeral Plan'"
+ );
+$smarty->assign('EmailAddress','smarty@example.com');
+
+```
+
+
+These are example `escape` template lines followed by the output
+
+```smarty
+{$articleTitle}
+'Stiff Opposition Expected to Casketless Funeral Plan'
+
+{$articleTitle|escape}
+'Stiff Opposition Expected to Casketless Funeral Plan'
+
+{$articleTitle|escape:'html'} {* escapes & " ' < > *}
+'Stiff Opposition Expected to Casketless Funeral Plan'
+
+{$articleTitle|escape:'htmlall'} {* escapes ALL html entities *}
+'Stiff Opposition Expected to Casketless Funeral Plan'
+
+click here
+click here
+
+{$articleTitle|escape:'quotes'}
+\'Stiff Opposition Expected to Casketless Funeral Plan\'
+
+{$EmailAddress|escape:"hexentity"}
+{$EmailAddress|escape:'mail'} {* this converts to email to text *}
+bob..snip..et
+
+{'mail@example.com'|escape:'mail'}
+smarty [AT] example [DOT] com
+
+{* the "rewind" parameter registers the current location *}
+click here
+
+```
+
+This snippet is useful for emails, but see also
+[`{mailto}`](../language-custom-functions/language-function-mailto.md)
+
+```smarty
+{* email address mangled *}
+{$EmailAddress|escape:'mail'}
+```
+
+See also [auto-escaping](../../api/configuring.md#enabling-auto-escaping), [escaping smarty parsing](../language-basic-syntax/language-escaping.md),
+[`{mailto}`](../language-custom-functions/language-function-mailto.md) and the [obfuscating email
+addresses](../../appendixes/tips.md#obfuscating-e-mail-addresses) pages.
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-from-charset.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-from-charset.md
new file mode 100644
index 0000000..25c4d2d
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-from-charset.md
@@ -0,0 +1,20 @@
+# from_charset
+
+`from_charset` is used to transcode a string from a given charset to the
+internal charset. This is the exact opposite of the [to_charset
+modifier](language-modifier-to-charset.md).
+
+## Parameters
+
+| Parameter Position | Type | Required | Possible Values | Default | Description |
+|--------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------|--------------|---------------------------------------------------------------|
+| 1 | string | No | `ISO-8859-1`, `UTF-8`, and any character set supported by [`mb_convert_encoding()`](https://www.php.net/mb_convert_encoding) | `ISO-8859-1` | The charset encoding the value is supposed to be decoded from |
+
+> **Note**
+>
+> Charset encoding should be handled by the application itself. This
+> modifier should only be used in cases where the application cannot
+> anticipate that a certain string is required in another encoding.
+
+See also [Configuring Smarty](../../api/configuring.md), [to_charset
+modifier](language-modifier-to-charset.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-indent.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-indent.md
new file mode 100644
index 0000000..9fa3540
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-indent.md
@@ -0,0 +1,67 @@
+# indent
+
+This indents a string on each line, default is 4. As an optional
+parameter, you can specify the number of characters to indent. As an
+optional second parameter, you can specify the character to use to
+indent with. For example: use `"\t"` for a tab.
+
+## Basic usage
+```smarty
+{$myVar|indent:4}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Default | Description |
+|--------------------|---------|----------|-------------|---------------------------------------------------|
+| 1 | integer | No | 4 | This determines how many characters to indent to. |
+| 2 | string | No | (one space) | This is the character used to indent with. |
+
+## Examples
+
+```php
+assign('articleTitle',
+ 'NJ judge to rule on nude beach.
+Sun or rain expected today, dark tonight.
+Statistics show that teen pregnancy drops off significantly after 25.'
+ );
+```
+
+Where template is:
+
+```smarty
+{$articleTitle}
+
+{$articleTitle|indent}
+
+{$articleTitle|indent:10}
+
+{$articleTitle|indent:1:"\t"}
+```
+
+Will output:
+
+```
+NJ judge to rule on nude beach.
+Sun or rain expected today, dark tonight.
+Statistics show that teen pregnancy drops off significantly after 25.
+
+ NJ judge to rule on nude beach.
+ Sun or rain expected today, dark tonight.
+ Statistics show that teen pregnancy drops off significantly after 25.
+
+ NJ judge to rule on nude beach.
+ Sun or rain expected today, dark tonight.
+ Statistics show that teen pregnancy drops off significantly after 25.
+
+ NJ judge to rule on nude beach.
+ Sun or rain expected today, dark tonight.
+ Statistics show that teen pregnancy drops off significantly after 25.
+```
+
+
+See also [`strip`](language-modifier-strip.md),
+[`wordwrap`](language-modifier-wordwrap.md) and
+[`spacify`](language-modifier-spacify.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-is_array.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-is_array.md
new file mode 100644
index 0000000..f6cfffc
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-is_array.md
@@ -0,0 +1,9 @@
+# is_array
+
+Return true if the variable passed to it is an array.
+
+## Basic usage
+
+```smarty
+{if $myVar|is_array}it's an array{/if}
+```
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-isset.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-isset.md
new file mode 100644
index 0000000..83e31df
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-isset.md
@@ -0,0 +1,11 @@
+# isset
+
+Returns true if the variable(s) passed to it are different from null.
+
+If multiple parameters are supplied then isset() will return true only if all of the parameters are
+not null.
+
+## Basic usage
+```smarty
+{if $myVar|isset}all set!{/if}
+```
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-join.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-join.md
new file mode 100644
index 0000000..9a04471
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-join.md
@@ -0,0 +1,26 @@
+# join
+
+Returns a string containing all the element of the given array
+with the separator string between each.
+
+## Basic usage
+
+For `$myArray` populated with `['a','b','c']`, the following will return the string `abc`.
+```smarty
+{$myArray|join}
+```
+
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|--------|----------|-------------------------------------------------------------|
+| 1 | string | No | glue used between array elements. Defaults to empty string. |
+
+## Examples
+
+
+For `$myArray` populated with `[1,2,3]`, the following will return the string `1-2-3`.
+```smarty
+{$myArray|join:"-"}
+```
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-json-encode.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-json-encode.md
new file mode 100644
index 0000000..4e70f0c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-json-encode.md
@@ -0,0 +1,27 @@
+# json_encode
+
+Transforms a value into a valid JSON string.
+
+## Basic usage
+```smarty
+{$user|json_encode}
+```
+Depending on the value of `$user` this would return a string in JSON-format, e.g. `{"username":"my_username","email":"my_username@smarty.net"}`.
+
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------------------------------------------------------------------------------------|
+| 1 | int | No | bitmask of flags, directly passed to [PHP's json_encode](https://www.php.net/json_encode) |
+
+
+## Examples
+
+By passing `16` as the second parameter, you can force json_encode to always format the JSON-string as an object.
+Without it, an array `$myArray = ["a","b"]` would be formatted as a javascript array:
+
+```smarty
+{$myArray|json_encode} # renders: ["a","b"]
+{$myArray|json_encode:16} # renders: {"0":"a","1":"b"}
+```
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-lower.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-lower.md
new file mode 100644
index 0000000..e5e6886
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-lower.md
@@ -0,0 +1,34 @@
+# lower
+
+This is used to lowercase a variable. This is equivalent to the PHP
+[`strtolower()`](https://www.php.net/strtolower) function.
+
+## Basic usage
+```smarty
+{$myVar|lower}
+```
+
+## Examples
+
+```php
+assign('articleTitle', 'Two Convicts Evade Noose, Jury Hung.');
+```
+
+Where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|lower}
+```
+
+This will output:
+
+```
+Two Convicts Evade Noose, Jury Hung.
+two convicts evade noose, jury hung.
+```
+
+See also [`upper`](language-modifier-upper.md) and
+[`capitalize`](language-modifier-capitalize.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-nl2br.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-nl2br.md
new file mode 100644
index 0000000..2808716
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-nl2br.md
@@ -0,0 +1,37 @@
+# nl2br
+
+All `"\n"` line breaks will be converted to html ` ` tags in the
+given variable. This is equivalent to the PHP\'s
+[`nl2br()`](https://www.php.net/nl2br) function.
+
+## Basic usage
+```smarty
+{$myVar|nl2br}
+```
+
+## Examples
+
+```php
+assign('articleTitle',
+ "Sun or rain expected\ntoday, dark tonight"
+ );
+
+```
+
+Where the template is:
+
+```smarty
+{$articleTitle|nl2br}
+```
+
+Will output:
+
+```
+Sun or rain expected today, dark tonight
+```
+
+See also [`word_wrap`](language-modifier-wordwrap.md),
+[`count_paragraphs`](language-modifier-count-paragraphs.md) and
+[`count_sentences`](language-modifier-count-sentences.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-noprint.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-noprint.md
new file mode 100644
index 0000000..5dbfaa3
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-noprint.md
@@ -0,0 +1,9 @@
+# noprint
+
+Always returns an empty string. This can be used to call a function or a method on an object that
+returns output, and suppress the output.
+
+## Basic usage
+```smarty
+{$controller->sendEmail()|noprint}
+```
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-number-format.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-number-format.md
new file mode 100644
index 0000000..44c3acf
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-number-format.md
@@ -0,0 +1,32 @@
+# number_format
+
+Allows you to format a number using decimals and a thousands-separator. By default, the number of decimals is 0
+and the number is rounded.
+
+## Basic usage
+```smarty
+{$num = 2000.151}
+{$num|number_format} # renders: 2,000
+```
+
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|--------|----------|---------------------------------------|
+| 1 | int | No | number of decimals (defaults to 0) |
+| 2 | string | No | decimal separator (defaults to ".") |
+| 3 | string | No | thousands-separator (defaults to ",") |
+
+
+## Examples
+
+```smarty
+{$num = 2000.151}
+{$num|number_format:2} # renders: 2,000.15
+```
+
+```smarty
+{$num = 2000.151}
+{$num|number_format:2:".":""} # renders: 2000.15
+```
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-raw.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-raw.md
new file mode 100644
index 0000000..e9cce97
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-raw.md
@@ -0,0 +1,8 @@
+# raw
+
+Prevents variable escaping when [auto-escaping](../../api/configuring.md#enabling-auto-escaping) is activated.
+
+## Basic usage
+```smarty
+{$myVar|raw}
+```
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-regex-replace.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-regex-replace.md
new file mode 100644
index 0000000..033d2a4
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-regex-replace.md
@@ -0,0 +1,55 @@
+# regex_replace
+
+A regular expression search and replace on a variable. Use the
+[`preg_replace()`](https://www.php.net/preg_replace) syntax from the PHP
+manual.
+
+## Basic usage
+```smarty
+{$myVar|regex_replace:"/foo/":"bar"}
+```
+
+> **Note**
+>
+> Although Smarty supplies this regex convenience modifier, it is
+> usually better to apply regular expressions in PHP, either via custom
+> functions or modifiers. Regular expressions are considered application
+> code and are not part of presentation logic.
+
+## Parameters
+
+| Parameter Position | Type | Required | Description |
+|--------------------|--------|----------|------------------------------------------------|
+| 1 | string | Yes | This is the regular expression to be replaced. |
+| 2 | string | Yes | This is the string of text to replace with. |
+
+
+## Examples
+
+```php
+assign('articleTitle', "Infertility unlikely to\nbe passed on, experts say.");
+
+```
+
+Where template is:
+
+```smarty
+{* replace each carriage return, tab and new line with a space *}
+
+{$articleTitle}
+{$articleTitle|regex_replace:"/[\r\t\n]/":" "}
+```
+
+Will output:
+
+```
+Infertility unlikely to
+be passed on, experts say.
+Infertility unlikely to be passed on, experts say.
+```
+
+
+See also [`replace`](language-modifier-replace.md) and
+[`escape`](language-modifier-escape.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-replace.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-replace.md
new file mode 100644
index 0000000..0e01ab4
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-replace.md
@@ -0,0 +1,45 @@
+# replace
+
+A simple search and replace on a variable. This is equivalent to the
+PHP's [`str_replace()`](https://www.php.net/str_replace) function.
+
+## Basic usage
+```smarty
+{$myVar|replace:"foo":"bar"}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Description |
+|--------------------|--------|----------|---------------------------------------------|
+| 1 | string | Yes | This is the string of text to be replaced. |
+| 2 | string | Yes | This is the string of text to replace with. |
+
+
+## Examples
+
+```php
+assign('articleTitle', "Child's Stool Great for Use in Garden.");
+
+```
+
+Where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|replace:'Garden':'Vineyard'}
+{$articleTitle|replace:' ':' '}
+```
+
+Will output:
+
+```
+Child's Stool Great for Use in Garden.
+Child's Stool Great for Use in Vineyard.
+Child's Stool Great for Use in Garden.
+```
+
+See also [`regex_replace`](language-modifier-regex-replace.md) and
+[`escape`](language-modifier-escape.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-round.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-round.md
new file mode 100644
index 0000000..c05b899
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-round.md
@@ -0,0 +1,35 @@
+# round
+
+Rounds a number to the specified precision.
+
+## Basic usage
+```smarty
+{3.14|round} # renders: 3
+```
+
+```smarty
+{3.141592|round:2} # renders: 3.14
+```
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|---------------------------|
+| 1 | int | No | precision (defaults to 0) |
+| 2 | int | No | mode (defaults to 1) |
+
+If 'precision' is negative, the number is rounded to the nearest power of 10. See examples below.
+
+The parameter 'mode' defines how the rounding is done. By default, 2.5 is rounded to 3, whereas 2.45 is rounded to 2.
+You usually don't need to change this. For more details on rounding modes,
+see [PHP's documentation on round](https://www.php.net/manual/en/function.round).
+
+## Examples
+
+By passing `16` as the second parameter, you can force json_encode to always format the JSON-string as an object.
+Without it, an array `$myArray = ["a","b"]` would be formatted as a javascript array:
+
+```smarty
+{$myArray|json_encode} # renders: ["a","b"]
+{$myArray|json_encode:16} # renders: {"0":"a","1":"b"}
+```
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-spacify.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-spacify.md
new file mode 100644
index 0000000..229e2d2
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-spacify.md
@@ -0,0 +1,44 @@
+# spacify
+
+`spacify` is a way to insert a space between every character of a
+variable. You can optionally pass a different character or string to
+insert.
+
+## Basic usage
+```smarty
+{$myVar|spacify}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Default | Description |
+|--------------------|--------|----------|-------------|-----------------------------------------------------------------|
+| 1 | string | No | *one space* | This what gets inserted between each character of the variable. |
+
+## Examples
+
+```php
+assign('articleTitle', 'Something Went Wrong in Jet Crash, Experts Say.');
+
+```
+
+Where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|spacify}
+{$articleTitle|spacify:"^^"}
+```
+
+Will output:
+
+```
+Something Went Wrong in Jet Crash, Experts Say.
+S o m e t h i n g W .... snip .... s h , E x p e r t s S a y .
+S^^o^^m^^e^^t^^h^^i^^n^^g^^ .... snip .... ^^e^^r^^t^^s^^ ^^S^^a^^y^^.
+```
+
+See also [`wordwrap`](language-modifier-wordwrap.md) and
+[`nl2br`](language-modifier-nl2br.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-split.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-split.md
new file mode 100644
index 0000000..caef884
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-split.md
@@ -0,0 +1,32 @@
+# split
+
+Splits a string into an array, using the optional second parameter as the separator.
+
+## Basic usage
+
+For `$chars` populated with `'abc'`, the following will produce a html list with 3 elements (a, b and c).
+```smarty
+
+ {foreach $chars|split as $char}
+ {$char|escape}
+ {/foreach}
+
+```
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|--------|----------|------------------------------------------------------------------------------------------------------------------------------|
+| 1 | string | No | separator used to split the string on. Defaults to empty string, causing each character in the source string to be separate. |
+
+## Examples
+
+
+For `$ids` populated with `'1,2,3'`, the following will produce a html list with 3 elements (1, 2 and 3).
+```smarty
+
+ {foreach $ids|split:',' as $id}
+ {$id|escape}
+ {/foreach}
+
+```
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-str-repeat.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-str-repeat.md
new file mode 100644
index 0000000..1ae1824
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-str-repeat.md
@@ -0,0 +1,14 @@
+# str_repeat
+
+Repeats the given value n times.
+
+## Basic usage
+```smarty
+{"hi"|str_repeat:2} # renders: hihi
+```
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-----------------------|
+| 1 | int | yes | number of repetitions |
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-string-format.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-string-format.md
new file mode 100644
index 0000000..6163a07
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-string-format.md
@@ -0,0 +1,43 @@
+# string_format
+
+This is a way to format strings, such as decimal numbers and such. Use
+the syntax for [`sprintf()`](https://www.php.net/sprintf) for the
+formatting.
+
+## Basic usage
+```smarty
+{$myVar|string_format:"%d"}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Description |
+|--------------------|--------|----------|---------------------------------------|
+| 1 | string | Yes | This is what format to use. (sprintf) |
+
+## Examples
+
+```php
+assign('number', 23.5787446);
+
+```
+
+Where template is:
+
+```smarty
+{$number}
+{$number|string_format:"%.2f"}
+{$number|string_format:"%d"}
+```
+
+Will output:
+
+```
+23.5787446
+23.58
+23
+```
+
+See also [`date_format`](language-modifier-date-format.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strip-tags.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strip-tags.md
new file mode 100644
index 0000000..7d94fdd
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strip-tags.md
@@ -0,0 +1,46 @@
+# strip_tags
+
+This strips out HTML markup tags, basically anything between `<` and `>`.
+
+## Basic usage
+```smarty
+{$myVar|strip_tags}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Default | Description |
+|--------------------|------|----------|---------|------------------------------------------------------------|
+| 1 | bool | No | TRUE | This determines whether the tags are replaced by ' ' or '' |
+
+## Examples
+
+```php
+assign('articleTitle',
+ "Blind Woman Gets New
+Kidney from Dad she Hasn't Seen in years ."
+ );
+
+```
+
+
+Where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|strip_tags} {* same as {$articleTitle|strip_tags:true} *}
+{$articleTitle|strip_tags:false}
+```
+
+Will output:
+
+```html
+Blind Woman Gets New Kidney from Dad she Hasn't Seen in years .
+Blind Woman Gets New Kidney from Dad she Hasn't Seen in years .
+Blind Woman Gets New Kidney from Dad she Hasn't Seen in years.
+```
+
+See also [`replace`](language-modifier-replace.md) and
+[`regex_replace`](language-modifier-regex-replace.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strip.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strip.md
new file mode 100644
index 0000000..b7bdc28
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strip.md
@@ -0,0 +1,42 @@
+# strip
+
+This replaces all spaces, newlines and tabs with a single space, or with
+the supplied string.
+
+## Basic usage
+```smarty
+{$myVar|strip}
+```
+
+> **Note**
+>
+> If you want to strip blocks of template text, use the built-in
+> [`{strip}`](../language-builtin-functions/language-function-strip.md) function.
+
+## Examples
+
+```php
+assign('articleTitle', "Grandmother of\neight makes\t hole in one.");
+$smarty->display('index.tpl');
+```
+
+Where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|strip}
+{$articleTitle|strip:' '}
+```
+
+Will output:
+
+```html
+Grandmother of
+eight makes hole in one.
+Grandmother of eight makes hole in one.
+Grandmother of eight makes hole in one.
+```
+
+See also [`{strip}`](../language-builtin-functions/language-function-strip.md) and
+[`truncate`](language-modifier-truncate.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strlen.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strlen.md
new file mode 100644
index 0000000..4c1f37a
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-strlen.md
@@ -0,0 +1,9 @@
+# strlen
+
+Returns the length (number of characters) in the given string, including spaces.
+
+## Basic usage
+```smarty
+{"Smarty"|strlen} # renders: 6
+{156|strlen} # renders: 3
+```
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-substr.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-substr.md
new file mode 100644
index 0000000..a79d8a4
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-substr.md
@@ -0,0 +1,25 @@
+# substr
+
+Returns a part (substring) of the given string starting at a given offset.
+
+## Basic usage
+```smarty
+{"Smarty"|substr:2} # renders: arty
+{"Smarty"|substr:2:3} # renders: art
+```
+
+## Parameters
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-----------------------------------------------------|
+| 1 | int | yes | offset (zero based, can be negative) |
+| 2 | int | no | length of substring returned (unlimited of omitted) |
+
+
+## Examples
+
+When used with a negative offset, the substring starts n characters from the end of the string counting backwards.
+```smarty
+{"Smarty"|substr:-2} # renders: ty
+{"Smarty"|substr:-2:1} # renders: t
+```
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-to-charset.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-to-charset.md
new file mode 100644
index 0000000..aa8cfd5
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-to-charset.md
@@ -0,0 +1,20 @@
+# to_charset
+
+`to_charset` is used to transcode a string from the internal charset to
+a given charset. This is the exact opposite of the [from_charset
+modifier](#language.modifier.from_charset).
+
+## Parameters
+
+| Parameter Position | Type | Required | Possible Values | Default | Description |
+|--------------------|--------|----------|------------------------------------------------------------------------------------------------------------------------------|--------------|-------------------------------------------------------------|
+| 1 | string | No | `ISO-8859-1`, `UTF-8`, and any character set supported by [`mb_convert_encoding()`](https://www.php.net/mb_convert_encoding) | `ISO-8859-1` | The charset encoding the value is supposed to be encoded to |
+
+> **Note**
+>
+> Charset encoding should be handled by the application itself. This
+> modifier should only be used in cases where the application cannot
+> anticipate that a certain string is required in another encoding.
+
+See also [Configuring Smarty](../../api/configuring.md), [from_charset
+modifier](language-modifier-from-charset.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-truncate.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-truncate.md
new file mode 100644
index 0000000..1cbb7ab
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-truncate.md
@@ -0,0 +1,57 @@
+# truncate
+
+This truncates a variable to a character length, the default is 80. As
+an optional second parameter, you can specify a string of text to
+display at the end if the variable was truncated. The characters in the
+string are included with the original truncation length. By default,
+`truncate` will attempt to cut off at a word boundary. If you want to
+cut off at the exact character length, pass the optional third parameter
+of TRUE.
+
+## Basic usage
+```smarty
+{$myVar|truncate:40:"..."}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Default | Description |
+|--------------------|---------|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 1 | integer | No | 80 | This determines how many characters to truncate to. |
+| 2 | string | No | \... | This is a text string that replaces the truncated text. Its length is included in the truncation length setting. |
+| 3 | boolean | No | FALSE | This determines whether or not to truncate at a word boundary with FALSE, or at the exact character with TRUE. |
+| 4 | boolean | No | FALSE | This determines whether the truncation happens at the end of the string with FALSE, or in the middle of the string with TRUE. Note that if this setting is TRUE, then word boundaries are ignored. |
+
+## Examples
+
+```php
+assign('articleTitle', 'Two Sisters Reunite after Eighteen Years at Checkout Counter.');
+```
+
+where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|truncate}
+{$articleTitle|truncate:30}
+{$articleTitle|truncate:30:""}
+{$articleTitle|truncate:30:"---"}
+{$articleTitle|truncate:30:"":true}
+{$articleTitle|truncate:30:"...":true}
+{$articleTitle|truncate:30:'..':true:true}
+```
+
+This will output:
+
+```
+Two Sisters Reunite after Eighteen Years at Checkout Counter.
+Two Sisters Reunite after Eighteen Years at Checkout Counter.
+Two Sisters Reunite after...
+Two Sisters Reunite after
+Two Sisters Reunite after---
+Two Sisters Reunite after Eigh
+Two Sisters Reunite after E...
+Two Sisters Re..ckout Counter.
+```
+
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-unescape.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-unescape.md
new file mode 100644
index 0000000..8e86030
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-unescape.md
@@ -0,0 +1,43 @@
+# unescape
+
+`unescape` is used to decode `entity`, `html` and `htmlall`. It counters
+the effects of the [escape modifier](language-modifier-escape.md) for the
+given types.
+
+## Basic usage
+```smarty
+{$myVar|unescape}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Possible Values | Default | Description |
+|--------------------|--------|----------|----------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------|
+| 1 | string | No | `html`, `htmlall`, `entity`, | `html` | This is the escape format to use. |
+| 2 | string | No | `ISO-8859-1`, `UTF-8`, and any character set supported by [`htmlentities()`](https://www.php.net/htmlentities) | `UTF-8` | The character set encoding passed to html\_entity\_decode() or htmlspecialchars\_decode() or mb\_convert\_encoding() et. al. |
+
+## Examples
+
+```php
+assign('articleTitle',
+ "Germans use "Ümlauts" and pay in €uro"
+ );
+```
+
+These are example `unescape` template lines followed by the output
+
+```smarty
+{$articleTitle}
+Germans use "Ümlauts" and pay in €uro
+
+{$articleTitle|unescape:"html"}
+Germans use "Ümlauts" and pay in €uro
+
+{$articleTitle|unescape:"htmlall"}
+Germans use "Ümlauts" and pay in €uro
+```
+
+See also [escaping smarty parsing](../language-basic-syntax/language-escaping.md), [escape
+modifier](language-modifier-escape.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-upper.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-upper.md
new file mode 100644
index 0000000..edce963
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-upper.md
@@ -0,0 +1,33 @@
+# upper
+
+This is used to uppercase a variable. This is equivalent to the PHP
+[`strtoupper()`](https://www.php.net/strtoupper) function.
+
+## Basic usage
+```smarty
+{$myVar|upper}
+```
+
+## Examples
+
+```php
+assign('articleTitle', "If Strike isn't Settled Quickly it may Last a While.");
+```
+
+Where template is:
+
+```smarty
+{$articleTitle}
+{$articleTitle|upper}
+```
+
+Will output:
+
+```
+If Strike isn't Settled Quickly it may Last a While.
+IF STRIKE ISN'T SETTLED QUICKLY IT MAY LAST A WHILE.
+```
+
+See also [`lower`](./language-modifier-lower.md) and
+[`capitalize`](language-modifier-capitalize.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-wordwrap.md b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-wordwrap.md
new file mode 100644
index 0000000..f3348fd
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-modifiers/language-modifier-wordwrap.md
@@ -0,0 +1,73 @@
+# wordwrap
+
+Wraps a string to a column width, the default is 80. As an optional
+second parameter, you can specify a string of text to wrap the text to
+the next line, the default is a carriage return `"\n"`. By default,
+`wordwrap` will attempt to wrap at a word boundary. If you want to cut
+off at the exact character length, pass the optional third parameter as
+TRUE. This is equivalent to the PHP
+[`wordwrap()`](https://www.php.net/wordwrap) function.
+
+## Basic usage
+```smarty
+{$myVar|wordwrap:30}
+```
+
+## Parameters
+
+| Parameter Position | Type | Required | Default | Description |
+|--------------------|---------|----------|---------|-----------------------------------------------------------------------------------------------|
+| 1 | integer | No | 80 | This determines how many columns to wrap to. |
+| 2 | string | No | \\n | This is the string used to wrap words with. |
+| 3 | boolean | No | FALSE | This determines whether to wrap at a word boundary (FALSE), or at the exact character (TRUE). |
+
+## Examples
+
+```php
+assign('articleTitle',
+ "Blind woman gets new kidney from dad she hasn't seen in years."
+ );
+
+```
+
+Where template is
+
+```smarty
+{$articleTitle}
+
+{$articleTitle|wordwrap:30}
+
+{$articleTitle|wordwrap:20}
+
+{$articleTitle|wordwrap:30:" \n"}
+
+{$articleTitle|wordwrap:26:"\n":true}
+```
+
+Will output:
+
+```html
+Blind woman gets new kidney from dad she hasn't seen in years.
+
+Blind woman gets new kidney
+from dad she hasn't seen in
+years.
+
+Blind woman gets new
+kidney from dad she
+hasn't seen in
+years.
+
+Blind woman gets new kidney
+from dad she hasn't seen in
+years.
+
+Blind woman gets new kidn
+ey from dad she hasn't se
+en in years.
+```
+
+See also [`nl2br`](language-modifier-nl2br.md) and
+[`{textformat}`](../language-custom-functions/language-function-textformat.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-variables/index.md b/src/includes/smarty-5.4.1/docs/designers/language-variables/index.md
new file mode 100644
index 0000000..0278c91
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-variables/index.md
@@ -0,0 +1,36 @@
+# Variables
+
+Smarty has several types of variables. The type of the
+variable depends on what symbol it is prefixed or enclosed within.
+
+- [Variables assigned from PHP](language-assigned-variables.md)
+- [Variables loaded from config files](language-config-variables.md)
+- [{$smarty} reserved variable](language-variables-smarty.md)
+
+Variables in Smarty can be either displayed directly or used as
+arguments for [tags](../language-basic-syntax/language-syntax-tags.md),
+[attributes](../language-basic-syntax/language-syntax-attributes.md) and
+[modifiers](../language-modifiers/index.md), inside conditional expressions, etc.
+To print a variable, simply enclose it in the
+[delimiters](../../designers/language-basic-syntax/language-escaping.md) so that it is the only thing
+contained between them.
+
+```smarty
+{$Name}
+
+{$product.part_no} {$product.description}
+
+{$Contacts[row].Phone}
+
+
+```
+
+## Scopes
+You can assign variables to specific [variable scopes](language-variable-scopes.md).
+
+
+> **Note**
+>
+> An easy way to examine assigned Smarty variables is with the
+> [debugging console](../chapter-debugging-console.md).
+
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-variables/language-assigned-variables.md b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-assigned-variables.md
new file mode 100644
index 0000000..9465a89
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-assigned-variables.md
@@ -0,0 +1,126 @@
+# Variables assigned from PHP
+
+Variables assigned from PHP are referenced by preceding them with a dollar
+(`$`) sign.
+
+## Examples
+
+```php
+assign('firstname', 'Doug');
+$smarty->assign('lastname', 'Evans');
+$smarty->assign('meetingPlace', 'New York');
+
+$smarty->display('index.tpl');
+
+```
+
+`index.tpl` source:
+
+```smarty
+Hello {$firstname} {$lastname}, glad to see you can make it.
+
+{* this will not work as $variables are case sensitive *}
+This weeks meeting is in {$meetingplace}.
+{* this will work *}
+This weeks meeting is in {$meetingPlace}.
+```
+
+This above would output:
+
+```html
+Hello Doug Evans, glad to see you can make it.
+
+This weeks meeting is in .
+This weeks meeting is in New York.
+```
+
+## Associative arrays
+
+You can also reference associative array variables by specifying the key
+after a dot "." symbol.
+
+```php
+assign('Contacts',
+ array('fax' => '555-222-9876',
+ 'email' => 'zaphod@slartibartfast.example.com',
+ 'phone' => array('home' => '555-444-3333',
+ 'cell' => '555-111-1234')
+ )
+ );
+$smarty->display('index.tpl');
+```
+
+`index.tpl` source:
+
+```smarty
+{$Contacts.fax}
+{$Contacts.email}
+{* you can print arrays of arrays as well *}
+{$Contacts.phone.home}
+{$Contacts.phone.cell}
+```
+
+this will output:
+
+```html
+555-222-9876
+zaphod@slartibartfast.example.com
+555-444-3333
+555-111-1234
+```
+
+## Array indexes
+
+You can reference arrays by their index, much like native PHP syntax.
+
+```php
+assign('Contacts', array(
+ '555-222-9876',
+ 'zaphod@slartibartfast.example.com',
+ array('555-444-3333',
+ '555-111-1234')
+ ));
+$smarty->display('index.tpl');
+```
+
+`index.tpl` source:
+
+```smarty
+{$Contacts[0]}
+{$Contacts[1]}
+{* you can print arrays of arrays as well *}
+{$Contacts[2][0]}
+{$Contacts[2][1]}
+```
+
+This will output:
+
+```html
+555-222-9876
+zaphod@slartibartfast.example.com
+555-444-3333
+555-111-1234
+```
+
+## Objects
+
+Properties of [objects](../../api/variables/objects.md) assigned from PHP
+can be referenced by specifying the property name after the `->` symbol.
+
+```smarty
+name: {$person->name}
+email: {$person->email}
+```
+
+this will output:
+
+```html
+name: Zaphod Beeblebrox
+email: zaphod@slartibartfast.example.com
+```
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-variables/language-config-variables.md b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-config-variables.md
new file mode 100644
index 0000000..89a90ce
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-config-variables.md
@@ -0,0 +1,79 @@
+# Variables loaded from config files
+
+Variables that are loaded from the [config files](../config-files.md) are
+referenced by enclosing them within `#hash_marks#`, or with the smarty
+variable [`$smarty.config`](language-variables-smarty.md#smartyconfig-languagevariablessmartyconfig). The
+later syntax is useful for embedding into quoted attribute values, or
+accessing variable values such as `$smarty.config.$foo`.
+
+## Examples
+
+Example config file - `foo.conf`:
+```ini
+pageTitle = "This is mine"
+bodyBgColor = '#eeeeee'
+tableBorderSize = 3
+tableBgColor = "#bbbbbb"
+rowBgColor = "#cccccc"
+```
+
+A template demonstrating the `#hash#` method:
+
+```smarty
+{config_load file='foo.conf'}
+
+ {#pageTitle#}
+
+
+
+ First
+ Last
+ Address
+
+
+
+
+```
+
+A template demonstrating the
+[`$smarty.config`](language-variables-smarty.md#smartyconfig-languagevariablessmartyconfig) method:
+
+```smarty
+{config_load file='foo.conf'}
+
+{$smarty.config.pageTitle}
+
+
+
+ First
+ Last
+ Address
+
+
+
+
+```
+
+Both examples would output:
+
+```html
+
+ This is mine
+
+
+
+ First
+ Last
+ Address
+
+
+
+
+```
+
+Config file variables cannot be used until after they are loaded in from
+a config file. This procedure is explained later in this document under
+[`{config_load}`](../language-builtin-functions/language-function-config-load.md).
+
+See also [variables](../language-basic-syntax/language-syntax-variables.md) and [$smarty reserved
+variables](language-variables-smarty.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-variables/language-variable-scopes.md b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-variable-scopes.md
new file mode 100644
index 0000000..e2b2446
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-variable-scopes.md
@@ -0,0 +1,60 @@
+# Variable scopes
+
+You have the choice to assign variables to the scope of the main Smarty
+object, data objects created with [`createData()`](../../programmers/api-functions/api-create-data.md),
+and template objects created with
+[`createTemplate()`](../../programmers/api-functions/api-create-template.md). These objects can be
+chained. A template sees all the variables of its own object and all
+variables assigned to the objects in its chain of parent objects.
+
+By default, templates which are rendered by
+[`$smarty->display(...)`](../../programmers/api-functions/api-display.md) or
+[`$smarty->fetch(...)`](../../programmers/api-functions/api-fetch.md) calls are automatically linked to
+the Smarty object variable scope.
+
+By assigning variables to individual data or template objects you have
+full control which variables can be seen by a template.
+
+```php
+assign('foo','smarty');
+
+// assign variables to data object scope
+$data = $smarty->createData();
+$data->assign('foo','data');
+$data->assign('bar','bar-data');
+
+// assign variables to other data object scope
+$data2 = $smarty->createData($data);
+$data2->assign('bar','bar-data2');
+
+// assign variable to template object scope
+$tpl = $smarty->createTemplate('index.tpl');
+$tpl->assign('bar','bar-template');
+
+// assign variable to template object scope with link to Smarty object
+$tpl2 = $smarty->createTemplate('index.tpl',$smarty);
+$tpl2->assign('bar','bar-template2');
+
+// This display() does see $foo='smarty' from the $smarty object
+$smarty->display('index.tpl');
+
+// This display() does see $foo='data' and $bar='bar-data' from the data object $data
+$smarty->display('index.tpl',$data);
+
+// This display() does see $foo='data' from the data object $data
+// and $bar='bar-data2' from the data object $data2
+$smarty->display('index.tpl',$data2);
+
+// This display() does see $bar='bar-template' from the template object $tpl
+$tpl->display(); // or $smarty->display($tpl);
+
+// This display() does see $bar='bar-template2' from the template object $tpl2
+// and $foo='smarty' form the Smarty object $foo
+$tpl2->display(); // or $smarty->display($tpl2);
+```
+
+See also [`assign()`](../../programmers/api-functions/api-assign.md),
+[`createData()`](../../programmers/api-functions/api-create-data.md)
+and [`createTemplate()`](../../programmers/api-functions/api-create-template.md).
diff --git a/src/includes/smarty-5.4.1/docs/designers/language-variables/language-variables-smarty.md b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-variables-smarty.md
new file mode 100644
index 0000000..cbeb668
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/designers/language-variables/language-variables-smarty.md
@@ -0,0 +1,155 @@
+# {$smarty} reserved variable
+
+The PHP reserved `{$smarty}` variable can be used to access several
+environment and request variables. The full list of them follows.
+
+## Request variables
+
+The [request variables](https://www.php.net/reserved.variables) such as
+`$_GET`, `$_POST`, `$_COOKIE`, `$_SERVER`, `$_ENV` and `$_SESSION` can
+be accessed as demonstrated in the examples below:
+
+```smarty
+{* display value of page from URL ($_GET) http://www.example.com/index.php?page=foo *}
+{$smarty.get.page}
+
+{* display the variable "page" from a form ($_POST['page']) *}
+{$smarty.post.page}
+
+{* display the value of the cookie "username" ($_COOKIE['username']) *}
+{$smarty.cookies.username}
+
+{* display the server variable "SERVER_NAME" ($_SERVER['SERVER_NAME'])*}
+{$smarty.server.SERVER_NAME}
+
+{* display the system environment variable "PATH" *}
+{$smarty.env.PATH}
+
+{* display the php session variable "id" ($_SESSION['id']) *}
+{$smarty.session.id}
+
+{* display the variable "username" from merged get/post/cookies/server/env *}
+{$smarty.request.username}
+```
+
+> **Note**
+>
+> For historical reasons `{$SCRIPT_NAME}` is shorthand for
+> `{$smarty.server.SCRIPT_NAME}`.
+>
+>
+> click me
+> click me
+
+> **Note**
+>
+> Although Smarty provides direct access to PHP super globals for
+> convenience, it should be used with caution. Directly accessing super
+> globals mixes underlying application code structure with templates. A
+> good practice is to assign specific needed values to template vars.
+
+## {$smarty.now}
+
+The current [timestamp](https://www.php.net/function.time) can be accessed
+with `{$smarty.now}`. The value reflects the number of seconds passed
+since the so-called Epoch on January 1, 1970, and can be passed directly
+to the [`date_format`](../language-modifiers/language-modifier-date-format.md) modifier for
+display. Note that [`time()`](https://www.php.net/function.time) is called
+on each invocation; eg a script that takes three seconds to execute with
+a call to `$smarty.now` at start and end will show the three-second
+difference.
+
+```smarty
+{* use the date_format modifier to show current date and time *}
+{$smarty.now|date_format:'%Y-%m-%d %H:%M:%S'}
+```
+
+## {$smarty.const}
+
+You can access PHP constant values directly.
+
+```php
+ **Note**
+>
+> Although Smarty provides direct access to PHP constants for
+> convenience, it is typically avoided as this is mixing underlying
+> application code structure into the templates. A good practice is to
+> assign specific needed values to template vars.
+
+## {$smarty.capture}
+
+Template output captured via the built-in
+[`{capture}..{/capture}`](../language-builtin-functions/language-function-capture.md) function can be
+accessed using the `{$smarty.capture}` variable. See the
+[`{capture}`](../language-builtin-functions/language-function-capture.md) page for more information.
+
+## {$smarty.config}
+
+`{$smarty.config}` variable can be used to refer to loaded [config
+variables](language-config-variables.md). `{$smarty.config.foo}` is a
+synonym for `{#foo#}`. See the
+[{config_load}](../language-builtin-functions/language-function-config-load.md) page for more info.
+
+## {$smarty.section}
+
+The `{$smarty.section}` variables can be used to refer to
+[`{section}`](../language-builtin-functions/language-function-section.md) loop properties. These have
+some very useful values such as `.first`, `.index`, etc.
+
+> **Note**
+>
+> The `{$smarty.foreach}` variable is no longer used with the new
+> [`{foreach}`](../language-builtin-functions/language-function-foreach.md) syntax, but is still
+> supported with Smarty 2.x style foreach syntax.
+
+## {$smarty.template}
+
+Returns the name of the current template being processed (without the
+directory).
+
+## {$smarty.template_object}
+
+Returns the template object of the current template being processed.
+
+## {$smarty.current_dir}
+
+Returns the name of the directory for the current template being
+processed if it is loaded from the filesystem (the default).
+
+## {$smarty.version}
+
+Returns the version of Smarty the template was compiled with.
+
+```smarty
+
+```
+
+## {$smarty.block.child}
+
+Returns block text from child template. See [Template
+inheritance](../../api/inheritance.md).
+
+## {$smarty.block.parent}
+
+Returns block text from parent template. See [Template
+inheritance](../../api/inheritance.md)
+
+## {$smarty.ldelim}, {$smarty.rdelim}
+
+These variables are used for printing the left-delimiter and
+right-delimiter value literally, the same as
+[`{ldelim},{rdelim}`](../language-builtin-functions/language-function-ldelim.md).
+
+See also [assigned variables](language-assigned-variables.md) and [config
+variables](language-config-variables.md)
diff --git a/src/includes/smarty-5.4.1/docs/features.md b/src/includes/smarty-5.4.1/docs/features.md
new file mode 100644
index 0000000..f9a873b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/features.md
@@ -0,0 +1,151 @@
+# Features
+
+Some of Smarty's features:
+
+- It is extremely fast.
+- It is efficient since the PHP parser does the dirty work.
+- No template parsing overhead, only compiles once.
+- It is smart about recompiling only the
+ template files that have changed.
+- You can easily create your own custom
+ [tags](api/extending/tags.md) and [modifiers](api/extending/modifiers.md), so the template language is
+ extremely extensible.
+- Configurable template [{delimiter}](designers/language-basic-syntax/language-escaping.md) tag
+ syntax, so you can use `{$foo}`, `{{$foo}}`, ``, etc.
+- The [`{if}..{elseif}..{else}..{/if}`](designers/language-builtin-functions/language-function-if.md)
+ constructs are passed to the PHP parser, so the `{if...}` expression
+ syntax can be as simple or as complex an evaluation as you like.
+- Allows unlimited nesting of
+ [`sections`](designers/language-builtin-functions/language-function-section.md), `if's` etc.
+- Built-in [caching](api/caching/basics.md) support
+- Arbitrary [template](api/resources.md) sources
+- [Template Inheritance](api/inheritance.md) for
+ easy management of template content.
+- [Plugin](api/extending/introduction.md) architecture
+
+## Separation of presentation from application code
+- This means templates can certainly contain logic under the condition
+ that it is for presentation only. Things such as
+ [including](designers/language-builtin-functions/language-function-include.md) other templates,
+ [alternating](designers/language-custom-functions/language-function-cycle.md) table row colors,
+ [upper-casing](designers/language-modifiers/language-modifier-upper.md) a variable,
+ [looping](designers/language-builtin-functions/language-function-foreach.md) over an array of data and
+ rendering it are examples of presentation logic.
+- This does not mean however that Smarty forces a separation of
+ business and presentation logic. Smarty has no knowledge of which is
+ which, so placing business logic in the template is your own doing.
+- Also, if you desire *no* logic in your templates you certainly can
+ do so by boiling the content down to text and variables only.
+
+## How does it work?
+
+Under the hood, Smarty "compiles" (basically copies and converts) the
+templates into PHP scripts. This happens once when each template is
+first invoked, and then the compiled versions are used from that point
+forward. Smarty takes care of this for you, so the template designer
+just edits the Smarty templates and never has to manage the compiled
+versions. This approach keeps the templates easy to maintain, and yet
+keeps execution times extremely fast since the compiled code is just
+PHP. And of course, all PHP scripts take advantage of PHP op-code caches
+such as APC.
+
+## Template Inheritance
+
+Template inheritance was introduced in Smarty 3. Before template
+inheritance, we managed our templates in
+pieces such as header and footer templates. This organization lends
+itself to many problems that require some hoop-jumping, such as managing
+content within the header/footer on a per-page basis. With template
+inheritance, instead of including other templates we maintain our
+templates as single pages. We can then manipulate blocks of content
+within by inheriting them. This makes templates intuitive, efficient and
+easy to manage. See
+[Template Inheritance](api/inheritance.md)
+for more info.
+
+## Why not use XML/XSLT syntax?
+There are a couple of good reasons. First, Smarty can be used for more
+than just XML/HTML based templates, such as generating emails,
+javascript, CSV, and PDF documents. Second, XML/XSLT syntax is even more
+verbose and fragile than PHP code! It is perfect for computers, but
+horrible for humans. Smarty is about being easy to read, understand and
+maintain.
+
+## Template Security
+Although Smarty insulates you from PHP, you still have the option to use
+it in certain ways if you wish. Template security forces the restriction
+of PHP (and select Smarty functions.) This is useful if you have third
+parties editing templates, and you don't want to unleash the full power
+of PHP or Smarty to them.
+
+## Integration
+Sometimes Smarty gets compared to Model-View-Controller (MVC)
+frameworks. Smarty is not an MVC, it is just the presentation layer,
+much like the View (V) part of an MVC. As a matter of fact, Smarty can
+easily be integrated as the view layer of an MVC. Many of the more
+popular ones have integration instructions for Smarty, or you may find
+some help here in the forums and documentation.
+
+## Other Template Engines
+Smarty is not the only engine following the *"Separate Programming Code
+from Presentation"* philosophy. For instance, Python has template
+engines built around the same principles such as Django Templates and
+CheetahTemplate. *Note: Languages such as Python do not mix with HTML
+natively, which give them the advantage of proper programming code
+separation from the outset. There are libraries available to mix Python
+with HTML, but they are typically avoided.*
+
+## What Smarty is Not
+
+Smarty is not an application development framework. Smarty is not an
+MVC. Smarty is not an alternative to Laravel, Symfony, CodeIgniter,
+or any of the other application development frameworks for PHP.
+
+Smarty is a template engine, and works as the (V)iew component of your
+application. Smarty can easily be coupled to any of the engines listed
+above as the view component. No different than any other software,
+Smarty has a learning curve. Smarty does not guarantee good application
+design or proper separation of presentation, this still needs to be
+addressed by a competent developer and web designer.
+
+## Is Smarty Right for Me?
+
+Smarty is not meant to be a tool for every job. The important thing is
+to identify if Smarty fits your needs. There are some important
+questions to ask yourself:
+
+### Template Syntax
+Are you content with PHP tags mixed with HTML? Are your
+web designers comfortable with PHP? Would your web designers prefer a
+tag-based syntax designed for presentation? Some experience working with
+both Smarty and PHP helps answer these questions.
+
+### The Business Case
+Is there a requirement to insulate the templates from
+PHP? Do you have untrusted parties editing templates that you do not
+wish to unleash the power of PHP to? Do you need to programmatically
+control what is and is not available within the templates? Smarty
+supplies these capabilities by design.
+
+## Feature set
+Does Smarty's features such as caching, template
+inheritance and plugin architecture save development cycles writing code
+that would be needed otherwise? Does the codebase or framework you plan
+on using have the features you need for the presentation component?
+
+## Sites using Smarty
+Many well-known PHP projects make use of Smarty such as XOOPS CMS, CMS Made Simple,
+Tiki Wiki CMS Groupware and X-Cart to name a few.
+
+## Summary
+Whether you are using Smarty for a small website or massive enterprise
+solution, it can accommodate your needs. There are numerous features
+that make Smarty a great choice:
+
+- separation of PHP from HTML/CSS just makes sense
+- readability for organization and management
+- security for 3rd party template access
+- feature completeness, and easily extendable to your own needs
+- massive user base, Smarty is here to stay
+- LGPL license for commercial use
+- 100% free to use, open source project
diff --git a/src/includes/smarty-5.4.1/docs/getting-started.md b/src/includes/smarty-5.4.1/docs/getting-started.md
new file mode 100644
index 0000000..3628fd2
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/getting-started.md
@@ -0,0 +1,197 @@
+# Getting started
+
+## Requirements
+Smarty can be run with PHP 7.2 to PHP 8.3.
+
+## Installation
+Smarty can be installed with [Composer](https://getcomposer.org/).
+
+To get the latest stable version of Smarty use:
+```shell
+composer require smarty/smarty
+```
+
+To get the latest, unreleased version, use:
+```shell
+composer require smarty/smarty:dev-master
+```
+
+To get the previous stable version of Smarty, Smarty 4, use:
+```shell
+composer require smarty/smarty:^4
+```
+
+Here's how you create an instance of Smarty in your PHP scripts:
+```php
+setTemplateDir('/some/template/dir');
+$smarty->setConfigDir('/some/config/dir');
+$smarty->setCompileDir('/some/compile/dir');
+$smarty->setCacheDir('/some/cache/dir');
+```
+
+The compile dir and cache dir need to be writable for the user running the PHP script.
+
+> **Note**
+>
+> This is usually user "nobody" and group "nobody". For OS X users, the
+> default is user "www" and group "www". If you are using Apache, you
+> can look in your `httpd.conf` file to see what user and group are
+> being used.
+
+```bash
+chown nobody:nobody /web/www.example.com/guestbook/templates_c/
+chmod 770 /web/www.example.com/guestbook/templates_c/
+
+chown nobody:nobody /web/www.example.com/guestbook/cache/
+chmod 770 /web/www.example.com/guestbook/cache/
+```
+
+You can verify if your system has the correct access rights for
+ these directories with [`testInstall()`](./programmers/api-functions/api-test-install.md):
+
+```php
+setTemplateDir('/some/template/dir');
+$smarty->setConfigDir('/some/config/dir');
+$smarty->setCompileDir('/some/compile/dir');
+$smarty->setCacheDir('/some/cache/dir');
+$smarty->testInstall();
+```
+
+## Basic usage
+
+Now, let's create the `index.tpl` file that Smarty will display. This
+needs to be located in the [`$template_dir`](./programmers/api-variables/variable-template-dir.md).
+
+```smarty
+{* Smarty *}
+Hello {$name|escape}, welcome to Smarty!
+```
+
+> **Note**
+>
+> `{* Smarty *}` is a template [comment](./designers/language-basic-syntax/language-syntax-comments.md). It
+> is not required, but it is good practice to start all your template
+> files with this comment. It makes the file easy to recognize
+> regardless of the file extension. For example, text editors could
+> recognize the file and turn on special syntax highlighting.
+
+Now lets edit our php file. We'll create an instance of Smarty,
+[`assign()`](./programmers/api-functions/api-assign.md) a template variable and
+[`display()`](./programmers/api-functions/api-display.md) the `index.tpl` file.
+
+```php
+setTemplateDir('/web/www.example.com/guestbook/templates/');
+$smarty->setCompileDir('/web/www.example.com/guestbook/templates_c/');
+$smarty->setConfigDir('/web/www.example.com/guestbook/configs/');
+$smarty->setCacheDir('/web/www.example.com/guestbook/cache/');
+
+$smarty->assign('name', 'Ned');
+$smarty->display('index.tpl');
+
+```
+
+> **Note**
+>
+> In our example, we are setting absolute paths to all the Smarty
+> directories. If `/web/www.example.com/guestbook/` is within your PHP
+> include\_path, then these settings are not necessary. However, it is
+> more efficient and (from experience) less error-prone to set them to
+> absolute paths. This ensures that Smarty is getting files from the
+> directories you intended.
+
+Now, run your PHP file. You should see *"Hello Ned, welcome to Smarty!"*
+
+You have completed the basic setup for Smarty!
+
+## Escaping
+You may have noticed that the example template above renders the `$name` variable using
+the [escape modifier](./designers/language-modifiers/language-modifier-escape.md). This
+modifier makes string 'safe' to use in the context of an HTML page.
+
+If you are primarily using Smarty for HTML-pages, it is recommended to enable automatic
+escaping. This way, you don't have to add `|escape` to every variable you use on a web page.
+Smarty will handle it automatically for you!
+
+Enable auto-escaping for HTML as follows:
+```php
+$smarty->setEscapeHtml(true);
+```
+
+## Extended Setup
+
+This is a continuation of the [basic installation](#installation), please read that first!
+
+A slightly more flexible way to set up Smarty is to extend the Smarty
+class and initialize your Smarty
+environment. So instead of repeatedly setting directory paths, assigning
+the same vars, etc., we can do that in one place.
+
+```php
+setTemplateDir('/web/www.example.com/guestbook/templates/');
+ $this->setCompileDir('/web/www.example.com/guestbook/templates_c/');
+ $this->setConfigDir('/web/www.example.com/guestbook/configs/');
+ $this->setCacheDir('/web/www.example.com/guestbook/cache/');
+
+ $this->setEscapeHtml(true);
+
+ $this->caching = Smarty::CACHING_LIFETIME_CURRENT;
+ $this->assign('app_name', 'Guest Book');
+ }
+
+}
+```
+
+Now, we can use `My_GuestBook` instead of `Smarty` in our scripts:
+```php
+assign('name', 'Ned');
+$smarty->display('index.tpl');
+```
diff --git a/src/includes/smarty-5.4.1/docs/img/favicon.ico b/src/includes/smarty-5.4.1/docs/img/favicon.ico
new file mode 100644
index 0000000..aec1d8e
Binary files /dev/null and b/src/includes/smarty-5.4.1/docs/img/favicon.ico differ
diff --git a/src/includes/smarty-5.4.1/docs/img/smarty.svg b/src/includes/smarty-5.4.1/docs/img/smarty.svg
new file mode 100644
index 0000000..cd8c866
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/img/smarty.svg
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/index.md b/src/includes/smarty-5.4.1/docs/index.md
new file mode 100644
index 0000000..5c788f9
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/index.md
@@ -0,0 +1,35 @@
+# Smarty Documentation
+Smarty is a template engine for PHP, facilitating the separation of presentation (HTML/CSS) from application logic.
+
+It allows you to write **templates**, using **variables**, **modifiers**, **functions** and **comments**, like this:
+```smarty
+{$title|escape}
+
+
+ The number of pixels is: {math equation="x * y" x=$height y=$width}.
+
+```
+
+When this template is rendered, with the value "Hello world" for the variable $title, 640 for $width,
+and 480 for $height, the result is:
+```html
+Hello world
+
+
+ The number of pixels is: 307200.
+
+```
+
+## Getting Started
+- [Getting Started](./getting-started.md)
+- [Philosophy](./philosophy.md) - or "Why do I need a template engine?"
+- [Features](./features.md) - or "Why do I want Smarty?"
+
+## Help
+- [Search or create an issue](https://github.com/smarty-php/smarty/issues)
+- [Upgrading from an older version](upgrading.md)
+- [Some random tips & tricks](./appendixes/tips.md)
+- [Troubleshooting](./appendixes/troubleshooting.md)
+
+## Source code
+- [Smarty repository at GitHub](https://github.com/smarty-php/smarty)
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/docs/philosophy.md b/src/includes/smarty-5.4.1/docs/philosophy.md
new file mode 100644
index 0000000..c5edd39
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/philosophy.md
@@ -0,0 +1,107 @@
+# Philosophy
+
+## What is Smarty?
+
+Smarty is a template engine for PHP. More specifically, it facilitates a
+manageable way to separate application logic and content from its
+presentation. This is best described in a situation where the
+application programmer and the template designer play different roles,
+or in most cases are not the same person.
+
+For example, let's say you are creating a web page that is displaying a
+newspaper article.
+
+- The article `$headline`, `$tagline`, `$author` and `$body` are
+ content elements, they contain no information about how they will be
+ presented. They are [passed](getting-started.md#basic-usage) into Smarty by the
+ application.
+
+- Then the template designer edits the templates and uses a
+ combination of HTML tags and [template tags](designers/language-basic-syntax/language-syntax-tags.md)
+ to format the presentation of these
+ [variables](designers/language-basic-syntax/language-syntax-variables.md) with elements such as
+ tables, div\'s, background colors, font sizes, style sheets, svg
+ etc.
+
+- One day the programmer needs to change the way the article content
+ is retrieved, ie a change in application logic. This change does not
+ affect the template designer, the content will still arrive in the
+ template exactly the same.
+
+- Likewise, if the template designer wants to completely redesign the
+ templates, this would require no change to the application logic.
+
+- Therefore, the programmer can make changes to the application logic
+ without the need to restructure templates, and the template designer
+ can make changes to templates without breaking application logic.
+
+## Goals
+
+The Smarty design was largely driven by these goals:
+- clean separation of presentation from application code
+- PHP backend, Smarty template frontend
+- complement PHP, not replace it
+- fast development/deployment for programmers and designers
+- quick and easy to maintain
+- syntax easy to understand, no PHP knowledge necessary
+- flexibility for custom development
+- security: insulation from PHP
+- free, open source
+
+
+
+## Two camps of thought
+
+When it comes to templating in PHP, there are basically two camps of
+thought. The first camp exclaims that \"PHP is a template engine\". This
+approach simply mixes PHP code with HTML. Although this approach is
+fastest from a pure script-execution point of view, many would argue
+that the PHP syntax is messy and complicated when mixed with tagged
+markup such as HTML.
+
+The second camp exclaims that presentation should be void of all
+programming code, and instead use simple tags to indicate where
+application content is revealed. This approach is common with other
+template engines (even in other programming languages), and is also the
+approach that Smarty takes. The idea is to keep the templates focused
+squarely on presentation, void of application code, and with as little
+overhead as possible.
+
+## Why is separating PHP from templates important?
+
+Two major benefits:
+
+- SYNTAX: Templates typically consist of semantic markup such as HTML.
+ PHP syntax works well for application code, but quickly degenerates
+ when mixed with HTML. Smarty\'s simple {tag} syntax is designed
+ specifically to express presentation. Smarty focuses your templates
+ on presentation and less on \"code\". This lends to quicker template
+ deployment and easier maintenance. Smarty syntax requires no working
+ knowledge of PHP, and is intuitive for programmers and
+ non-programmers alike.
+
+- INSULATION: When PHP is mixed with templates, there are no
+ restrictions on what type of logic can be injected into a template.
+ Smarty insulates the templates from PHP, creating a controlled
+ separation of presentation from business logic. Smarty also has
+ security features that can further enforce restrictions on
+ templates.
+
+## Web designers and PHP
+
+A common question: "Web designers have to learn a syntax anyway, why
+not PHP?" Of course web designers can learn PHP, and they may already
+be familiar with it. The issue isn't their ability to learn PHP, it is
+about the consequences of mixing PHP with HTML. If designers use PHP, it
+is too easy to add code into templates that doesn't belong there (you
+just handed them a swiss-army knife when they just needed a knife.) You
+can teach them the rules of application design, but this is probably
+something they don't really need to learn (now they are developers!)
+The PHP manual is also an overwhelming pile of information to sift
+through. It is like handing the owner of a car the factory assembly
+manual when all they need is the owners manual. Smarty gives web
+designers exactly the tools they need, and gives developers fine-grained
+control over those tools. The simplicity of the tag-based syntax is also
+a huge welcome for designers, it helps them streamline the organization
+and management of templates.
+
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/add-extension.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/add-extension.md
new file mode 100644
index 0000000..e69de29
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-add-plugins-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-add-plugins-dir.md
new file mode 100644
index 0000000..ec9741b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-add-plugins-dir.md
@@ -0,0 +1,42 @@
+addPluginsDir()
+
+add a directory to the list of directories where plugins are stored
+
+Description
+===========
+
+Smarty
+
+addPluginsDir
+
+string\|array
+
+plugins\_dir
+
+
+ addPluginsDir('./plugins_1');
+
+ // add multiple directories where plugins are stored
+ $smarty->setPluginsDir(array(
+ './plugins_2',
+ './plugins_3',
+ ));
+
+ // view the plugins dir chain
+ var_dump($smarty->getPluginsDir());
+
+ // chaining of method calls
+ $smarty->setPluginsDir('./plugins')
+ ->addPluginsDir('./plugins_1')
+ ->addPluginsDir('./plugins_2');
+
+ ?>
+
+
+
+See also [`getPluginsDir()`](#api.get.plugins.dir),
+[`setPluginsDir()`](#api.set.plugins.dir) and
+[`$plugins_dir`](#variable.plugins.dir).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-append.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-append.md
new file mode 100644
index 0000000..d9acff8
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-append.md
@@ -0,0 +1,60 @@
+append()
+
+append an element to an assigned array
+
+Description
+===========
+
+void
+
+append
+
+mixed
+
+var
+
+void
+
+append
+
+string
+
+varname
+
+mixed
+
+var
+
+bool
+
+merge
+
+If you append to a string value, it is converted to an array value and
+then appended to. You can explicitly pass name/value pairs, or
+associative arrays containing the name/value pairs. If you pass the
+optional third parameter of TRUE, the value will be merged with the
+current array instead of appended.
+
+NOTE.PARAMETER.MERGE
+
+
+ append('foo', 'Fred');
+ // After this line, foo will now be seen as an array in the template
+ $smarty->append('foo', 'Albert');
+
+ $array = array(1 => 'one', 2 => 'two');
+ $smarty->append('X', $array);
+ $array2 = array(3 => 'three', 4 => 'four');
+ // The following line will add a second element to the X array
+ $smarty->append('X', $array2);
+
+ // passing an associative array
+ $smarty->append(array('city' => 'Lincoln', 'state' => 'Nebraska'));
+ ?>
+
+
+
+See also [`assign()`](#api.assign) and
+[`getTemplateVars()`](#api.get.template.vars)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-assign.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-assign.md
new file mode 100644
index 0000000..31f6a15
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-assign.md
@@ -0,0 +1,83 @@
+assign()
+
+assign variables/objects to the templates
+
+Description
+===========
+
+void
+
+assign
+
+mixed
+
+var
+
+void
+
+assign
+
+string
+
+varname
+
+mixed
+
+var
+
+bool
+
+nocache
+
+You can explicitly pass name/value pairs, or associative arrays
+containing the name/value pairs.
+
+If you pass the optional third `nocache` parameter of TRUE, the variable
+is assigned as nocache variable. See
+[`Cacheability of Variables`](#cacheability.variables) for details.
+
+> **Note**
+>
+> When you assign/register objects to templates, be sure that all
+> properties and methods accessed from the template are for presentation
+> purposes only. It is very easy to inject application logic through
+> objects, and this leads to poor designs that are difficult to manage.
+> See the Best Practices section of the Smarty website.
+
+
+ assign('Name', 'Fred');
+ $smarty->assign('Address', $address);
+
+ // passing an associative array
+ $smarty->assign(array('city' => 'Lincoln', 'state' => 'Nebraska'));
+
+ // passing an array
+ $myArray = array('no' => 10, 'label' => 'Peanuts');
+ $smarty->assign('foo',$myArray);
+
+ // passing a row from a database (eg adodb)
+ $sql = 'select id, name, email from contacts where contact ='.$id;
+ $smarty->assign('contact', $db->getRow($sql));
+ ?>
+
+These are accessed in the template with
+
+
+ {* note the vars are case sensitive like php *}
+ {$Name}
+ {$Address}
+ {$city}
+ {$state}
+
+ {$foo.no}, {$foo.label}
+ {$contact.id}, {$contact.name},{$contact.email}
+
+To access more complex array assignments see
+[`{foreach}`](#language.function.foreach) and
+[`{section}`](#language.function.section)
+
+See also [`getTemplateVars()`](#api.get.template.vars),
+[`clearAssign()`](#api.clear.assign), [`append()`](#api.append) and
+[`{assign}`](#language.function.assign)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-all-assign.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-all-assign.md
new file mode 100644
index 0000000..cc75fad
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-all-assign.md
@@ -0,0 +1,34 @@
+clearAllAssign()
+
+clears the values of all assigned variables
+
+Description
+===========
+
+void
+
+clearAllAssign
+
+
+ assign('Name', 'Fred');
+ $smarty->assign('Address', $address);
+
+ // will output above
+ print_r( $smarty->getTemplateVars() );
+
+ // clear all assigned variables
+ $smarty->clearAllAssign();
+
+ // will output nothing
+ print_r( $smarty->getTemplateVars() );
+
+ ?>
+
+
+
+See also [`clearAssign()`](#api.clear.assign),
+[`clearConfig()`](#api.clear.config),
+[`getTemplateVars()`](#api.get.template.vars), [`assign()`](#api.assign)
+and [`append()`](#api.append)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-all-cache.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-all-cache.md
new file mode 100644
index 0000000..55cbe57
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-all-cache.md
@@ -0,0 +1,37 @@
+clearAllCache()
+
+clears the entire template cache
+
+Description
+===========
+
+void
+
+clearAllCache
+
+int
+
+expire\_time
+
+As an optional parameter, you can supply a minimum age in seconds the
+cache files must be before they will get cleared.
+
+> **Note**
+>
+> Since Smarty version 3.1.14 it is possible to delete cache files by
+> their individual expiration time at creation by passing constant
+> SMARTY::CLEAR\_EXPIRED as `expire_time` parameter.
+
+
+ clearAllCache();
+
+ // clears all files over one hour old
+ $smarty->clearAllCache(3600);
+ ?>
+
+
+
+See also [`clearCache()`](#api.clear.cache),
+[`isCached()`](#api.is.cached) and the [caching](#caching) page.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-assign.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-assign.md
new file mode 100644
index 0000000..ac0731e
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-assign.md
@@ -0,0 +1,32 @@
+clearAssign()
+
+clears the value of an assigned variable
+
+Description
+===========
+
+void
+
+clearAssign
+
+mixed
+
+var
+
+This can be a single value, or an array of values.
+
+
+ clearAssign('Name');
+
+ // clears multiple variables
+ $smarty->clearAssign(array('Name', 'Address', 'Zip'));
+ ?>
+
+
+
+See also [`clearAllAssign()`](#api.clear.all.assign),
+[`clearConfig()`](#api.clear.config),
+[`getTemplateVars()`](#api.get.template.vars), [`assign()`](#api.assign)
+and [`append()`](#api.append)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-cache.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-cache.md
new file mode 100644
index 0000000..3e17d80
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-cache.md
@@ -0,0 +1,60 @@
+clearCache()
+
+clears the cache for a specific template
+
+Description
+===========
+
+void
+
+clearCache
+
+string
+
+template
+
+string
+
+cache\_id
+
+string
+
+compile\_id
+
+int
+
+expire\_time
+
+- If you have [multiple caches](#caching.multiple.caches) for a
+ template, you can clear a specific cache by supplying the `cache_id`
+ as the second parameter.
+
+- You can also pass a [`$compile_id`](#variable.compile.id) as a third
+ parameter. You can [group templates together](#caching.groups) so
+ they can be removed as a group, see the [caching section](#caching)
+ for more information.
+
+- As an optional fourth parameter, you can supply a minimum age in
+ seconds the cache file must be before it will get cleared.
+
+ > **Note**
+ >
+ > Since Smarty version 3.1.14 it is possible to delete cache files
+ > by their individual expiration time at creation by passing
+ > constant SMARTY::CLEAR\_EXPIRED as fourth parameter.
+
+
+
+
+ clearCache('index.tpl');
+
+ // clear the cache for a particular cache id in an multiple-cache template
+ $smarty->clearCache('index.tpl', 'MY_CACHE_ID');
+ ?>
+
+
+
+See also [`clearAllCache()`](#api.clear.all.cache) and
+[`caching`](#caching) section.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-compiled-tpl.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-compiled-tpl.md
new file mode 100644
index 0000000..dfa688e
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-compiled-tpl.md
@@ -0,0 +1,44 @@
+clearCompiledTemplate()
+
+clears the compiled version of the specified template resource
+
+Description
+===========
+
+void
+
+clearCompiledTemplate
+
+string
+
+tpl\_file
+
+string
+
+compile\_id
+
+int
+
+exp\_time
+
+This clears the compiled version of the specified template resource, or
+all compiled template files if one is not specified. If you pass a
+[`$compile_id`](#variable.compile.id) only the compiled template for
+this specific [`$compile_id`](#variable.compile.id) is cleared. If you
+pass an exp\_time, then only compiled templates older than `exp_time`
+seconds are cleared, by default all compiled templates are cleared
+regardless of their age. This function is for advanced use only, not
+normally needed.
+
+
+ clearCompiledTemplate('index.tpl');
+
+ // clear entire compile directory
+ $smarty->clearCompiledTemplate();
+ ?>
+
+
+
+See also [`clearCache()`](#api.clear.cache).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-config.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-config.md
new file mode 100644
index 0000000..43e86be
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-clear-config.md
@@ -0,0 +1,35 @@
+clearConfig()
+
+clears assigned config variables
+
+Description
+===========
+
+void
+
+clearConfig
+
+string
+
+var
+
+This clears all assigned [config variables](#language.config.variables).
+If a variable name is supplied, only that variable is cleared.
+
+
+ clearConfig();
+
+ // clear one variable
+ $smarty->clearConfig('foobar');
+ ?>
+
+
+
+See also [`getConfigVars()`](#api.get.config.vars),
+[`config variables`](#language.config.variables),
+[`config files`](#config.files),
+[`{config_load}`](#language.function.config.load),
+[`configLoad()`](#api.config.load) and
+[`clearAssign()`](#api.clear.assign).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-compile-all-config.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-compile-all-config.md
new file mode 100644
index 0000000..35497d9
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-compile-all-config.md
@@ -0,0 +1,61 @@
+compileAllConfig()
+
+compiles all known config files
+
+Description
+===========
+
+string
+
+compileAllConfig
+
+string
+
+extension
+
+boolean
+
+force
+
+integer
+
+timelimit
+
+integer
+
+maxerror
+
+This function compiles config files found in the
+[`$config_dir`](#variable.config.dir) folder. It uses the following
+parameters:
+
+- `extension` is an optional string which defines the file extension
+ for the config files. The default is \".conf\".
+
+- `force` is an optional boolean which controls if only modified
+ (false) or all (true) config files shall be compiled. The default is
+ \"false\".
+
+- `timelimit` is an optional integer to set a runtime limit in seconds
+ for the compilation process. The default is no limit.
+
+- `maxerror` is an optional integer to set an error limit. If more
+ config files failed to compile the function will be aborted. The
+ default is no limit.
+
+> **Note**
+>
+> This function may not create desired results in all configurations.
+> Use is on own risk.
+
+
+ compileAllConfig('.config',true);
+
+ ?>
+
+
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-compile-all-templates.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-compile-all-templates.md
new file mode 100644
index 0000000..2be22ee
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-compile-all-templates.md
@@ -0,0 +1,71 @@
+compileAllTemplates()
+
+compiles all known templates
+
+Description
+===========
+
+string
+
+compileAllTemplates
+
+string
+
+extension
+
+boolean
+
+force
+
+integer
+
+timelimit
+
+integer
+
+maxerror
+
+This function compiles template files found in the
+[`$template_dir`](#variable.template.dir) folder. It uses the following
+parameters:
+
+- `extension` is an optional string which defines the file extension
+ for the template files. The default is \".tpl\".
+
+- `force` is an optional boolean which controls if only modified
+ (false) or all (true) templates shall be compiled. The default is
+ \"false\".
+
+- `timelimit` is an optional integer to set a runtime limit in seconds
+ for the compilation process. The default is no limit.
+
+- `maxerror` is an optional integer to set an error limit. If more
+ templates failed to compile the function will be aborted. The
+ default is no limit.
+
+> **Note**
+>
+> This function may not create desired results in all configurations.
+> Use is on own risk.
+
+> **Note**
+>
+> If any template requires registered plugins, filters or objects you
+> must register all of them before running this function.
+
+> **Note**
+>
+> If you are using template inheritance this function will create
+> compiled files of parent templates which will never be used.
+
+
+ compileAllTemplates('.tpl',true);
+
+ ?>
+
+
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-config-load.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-config-load.md
new file mode 100644
index 0000000..bf6001f
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-config-load.md
@@ -0,0 +1,47 @@
+configLoad()
+
+loads config file data and assigns it to the template
+
+Description
+===========
+
+void
+
+configLoad
+
+string
+
+file
+
+string
+
+section
+
+This loads [config file](#config.files) data and assigns it to the
+template. This works identically to the template
+[`{config_load}`](#language.function.config.load) function.
+
+> **Note**
+>
+> As of Smarty 2.4.0, assigned template variables are kept across
+> invocations of [`fetch()`](#api.fetch) and
+> [`display()`](#api.display). Config vars loaded from `configLoad()`
+> are always global in scope. Config files are also compiled for faster
+> execution, and respect the [`$force_compile`](#variable.force.compile)
+> and [`$compile_check`](#variable.compile.check) settings.
+
+
+ configLoad('my.conf');
+
+ // load a section
+ $smarty->configLoad('my.conf', 'foobar');
+ ?>
+
+
+
+See also [`{config_load}`](#language.function.config.load),
+[`getConfigVars()`](#api.get.config.vars),
+[`clearConfig()`](#api.clear.config), and
+[`config variables`](#language.config.variables)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-create-data.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-create-data.md
new file mode 100644
index 0000000..dc03ad9
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-create-data.md
@@ -0,0 +1,52 @@
+createData()
+
+creates a data object
+
+Description
+===========
+
+string
+
+createData
+
+object
+
+parent
+
+string
+
+createData
+
+This creates a data object which will hold assigned variables. It uses
+the following parameters:
+
+- `parent` is an optional parameter. It is an uplink to the main
+ Smarty object, a another user-created data object or to user-created
+ template object. These objects can be chained. Templates can access
+ variables assigned to any of the objects in it\'s parent chain.
+
+Data objects are used to create scopes for assigned variables. They can
+be used to control which variables are seen by which templates.
+
+
+ createData();
+
+ // assign variable to data scope
+ $data->assign('foo','bar');
+
+ // create template object which will use variables from data object
+ $tpl = $smarty->createTemplate('index.tpl',$data);
+
+ // display the template
+ $tpl->display();
+ ?>
+
+
+
+See also [`display()`](#api.display), and
+[`createTemplate()`](#api.create.template),
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-create-template.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-create-template.md
new file mode 100644
index 0000000..097b7df
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-create-template.md
@@ -0,0 +1,99 @@
+createTemplate()
+
+returns a template object
+
+Description
+===========
+
+Smarty\_Internal\_Template
+
+createTemplate
+
+string
+
+template
+
+object
+
+parent
+
+Smarty\_Internal\_Template
+
+createTemplate
+
+string
+
+template
+
+array
+
+data
+
+Smarty\_Internal\_Template
+
+createTemplate
+
+string
+
+template
+
+string
+
+cache\_id
+
+string
+
+compile\_id
+
+object
+
+parent
+
+Smarty\_Internal\_Template
+
+createTemplate
+
+string
+
+template
+
+string
+
+cache\_id
+
+string
+
+compile\_id
+
+array
+
+data
+
+This creates a template object which later can be rendered by the
+[display](#api.display) or [fetch](#api.fetch) method. It uses the
+following parameters:
+
+- `template` must be a valid [template resource](#resources) type and
+ path.
+
+
+
+
+ createTemplate('index.tpl');
+
+ // assign variable to template scope
+ $tpl->assign('foo','bar');
+
+ // display the template
+ $tpl->display();
+ ?>
+
+
+
+See also [`display()`](#api.display), and
+[`templateExists()`](#api.template.exists).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-disable-security.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-disable-security.md
new file mode 100644
index 0000000..1166828
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-disable-security.md
@@ -0,0 +1,15 @@
+disableSecurity()
+
+disables template security
+
+Description
+===========
+
+string
+
+disableSecurity
+
+This disables security checking on templates.
+
+See also [`enableSecurity()`](#api.enable.security), and
+[Security](#advanced.features.security).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-display.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-display.md
new file mode 100644
index 0000000..ced7513
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-display.md
@@ -0,0 +1,84 @@
+display()
+
+displays the template
+
+Description
+===========
+
+void
+
+display
+
+string
+
+template
+
+string
+
+cache\_id
+
+string
+
+compile\_id
+
+This displays the contents of a template. To return the contents of a
+template into a variable, use [`fetch()`](#api.fetch). Supply a valid
+[template resource](#resources) type and path. As an optional second
+parameter, you can pass a `$cache_id`, see the [caching
+section](#caching) for more information.
+
+PARAMETER.COMPILEID
+
+
+ setCaching(true);
+
+ // only do db calls if cache doesn't exist
+ if(!$smarty->isCached('index.tpl')) {
+
+ // dummy up some data
+ $address = '245 N 50th';
+ $db_data = array(
+ 'City' => 'Lincoln',
+ 'State' => 'Nebraska',
+ 'Zip' => '68502'
+ );
+
+ $smarty->assign('Name', 'Fred');
+ $smarty->assign('Address', $address);
+ $smarty->assign('data', $db_data);
+
+ }
+
+ // display the output
+ $smarty->display('index.tpl');
+ ?>
+
+
+
+Use the syntax for [template resources](#resources) to display files
+outside of the [`$template_dir`](#variable.template.dir) directory.
+
+
+ display('/usr/local/include/templates/header.tpl');
+
+ // absolute filepath (same thing)
+ $smarty->display('file:/usr/local/include/templates/header.tpl');
+
+ // windows absolute filepath (MUST use "file:" prefix)
+ $smarty->display('file:C:/www/pub/templates/header.tpl');
+
+ // include from template resource named "db"
+ $smarty->display('db:header.tpl');
+ ?>
+
+
+
+See also [`fetch()`](#api.fetch) and
+[`templateExists()`](#api.template.exists).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-enable-security.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-enable-security.md
new file mode 100644
index 0000000..72ee38b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-enable-security.md
@@ -0,0 +1,41 @@
+enableSecurity()
+
+enables template security
+
+Description
+===========
+
+string
+
+enableSecurity
+
+string
+
+securityclass
+
+string
+
+enableSecurity
+
+object
+
+securityobject
+
+string
+
+enableSecurity
+
+This enables security checking on templates. It uses the following
+parameters:
+
+- `securityclass` is an optional parameter. It\'s the name of the
+ class with defines the security policy parameters.
+
+- `securityobject` is an optional parameter. It\'s the object with
+ defines the security policy parameters.
+
+For the details how to setup a security policy see the
+[Security](#advanced.features.security) section.
+
+See also [`disableSecurity()`](#api.disable.security), and
+[Security](#advanced.features.security).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-fetch.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-fetch.md
new file mode 100644
index 0000000..491c28d
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-fetch.md
@@ -0,0 +1,91 @@
+fetch()
+
+returns the template output
+
+Description
+===========
+
+string
+
+fetch
+
+string
+
+template
+
+string
+
+cache\_id
+
+string
+
+compile\_id
+
+This returns the template output instead of [displaying](#api.display)
+it. Supply a valid [template resource](#resources) type and path. As an
+optional second parameter, you can pass a `$cache id`, see the [caching
+section](#caching) for more information.
+
+PARAMETER.COMPILEID
+
+
+ setCaching(true);
+
+ // set a separate cache_id for each unique URL
+ $cache_id = md5($_SERVER['REQUEST_URI']);
+
+ // capture the output
+ $output = $smarty->fetch('index.tpl', $cache_id);
+
+ // do something with $output here
+ echo $output;
+ ?>
+
+
+
+The `email_body.tpl` template
+
+
+ Dear {$contact_info.name},
+
+ Welcome and thank you for signing up as a member of our user group.
+
+ Click on the link below to login with your user name
+ of '{$contact_info.username}' so you can post in our forums.
+
+ {$login_url}
+
+ List master
+
+ {textformat wrap=40}
+ This is some long-winded disclaimer text that would automatically get wrapped
+ at 40 characters. This helps make the text easier to read in mail programs that
+ do not wrap sentences for you.
+ {/textformat}
+
+
+
+The php script using the PHP [`mail()`](https://www.php.net/function.mail)
+function
+
+
+ assign('contact_info',$contact_info);
+ $smarty->assign('login_url',"http://{$_SERVER['SERVER_NAME']}/login");
+
+ mail($contact_info['email'], 'Thank You', $smarty->fetch('email_body.tpl'));
+
+ ?>
+
+
+
+See also [`{fetch}`](#language.function.fetch)
+[`display()`](#api.display), [`{eval}`](#language.function.eval), and
+[`templateExists()`](#api.template.exists).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-config-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-config-dir.md
new file mode 100644
index 0000000..f41472c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-config-dir.md
@@ -0,0 +1,40 @@
+getConfigDir()
+
+return the directory where config files are stored
+
+Description
+===========
+
+string\|array
+
+getConfigDir
+
+string
+
+key
+
+
+ setConfigDir(array(
+ 'one' => './config',
+ 'two' => './config_2',
+ 'three' => './config_3',
+ ));
+
+ // get all directories where config files are stored
+ $config_dir = $smarty->getConfigDir();
+ var_dump($config_dir); // array
+
+ // get directory identified by key
+ $config_dir = $smarty->getConfigDir('one');
+ var_dump($config_dir); // string
+
+ ?>
+
+
+
+See also [`setConfigDir()`](#api.set.config.dir),
+[`addConfigDir()`](#api.add.config.dir) and
+[`$config_dir`](#variable.config.dir).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-config-vars.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-config-vars.md
new file mode 100644
index 0000000..f252e86
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-config-vars.md
@@ -0,0 +1,37 @@
+getConfigVars()
+
+returns the given loaded config variable value
+
+Description
+===========
+
+array
+
+getConfigVars
+
+string
+
+varname
+
+If no parameter is given, an array of all loaded [config
+variables](#language.config.variables) is returned.
+
+
+ getConfigVars('foo');
+
+ // get all loaded config template vars
+ $all_config_vars = $smarty->getConfigVars();
+
+ // take a look at them
+ print_r($all_config_vars);
+ ?>
+
+
+
+See also [`clearConfig()`](#api.clear.config),
+[`{config_load}`](#language.function.config.load),
+[`configLoad()`](#api.config.load) and
+[`getTemplateVars()`](#api.get.template.vars).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-plugins-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-plugins-dir.md
new file mode 100644
index 0000000..aa60355
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-plugins-dir.md
@@ -0,0 +1,31 @@
+getPluginsDir()
+
+return the directory where plugins are stored
+
+Description
+===========
+
+array
+
+getPluginsDir
+
+
+ setPluginsDir(array(
+ './plugins',
+ './plugins_2',
+ ));
+
+ // get all directories where plugins are stored
+ $config_dir = $smarty->getPluginsDir();
+ var_dump($config_dir); // array
+
+ ?>
+
+
+
+See also [`setPluginsDir()`](#api.set.plugins.dir),
+[`addPluginsDir()`](#api.add.plugins.dir) and
+[`$plugins_dir`](#variable.plugins.dir).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-registered-object.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-registered-object.md
new file mode 100644
index 0000000..a7c920e
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-registered-object.md
@@ -0,0 +1,36 @@
+getRegisteredObject()
+
+returns a reference to a registered object
+
+Description
+===========
+
+array
+
+getRegisteredObject
+
+string
+
+object\_name
+
+This is useful from within a custom function when you need direct access
+to a [registered object](#api.register.object). See the
+[objects](#advanced.features.objects) page for more info.
+
+
+ getRegisteredObject($params['object']);
+ // use $obj_ref is now a reference to the object
+ }
+ }
+ ?>
+
+
+
+See also [`registerObject()`](#api.register.object),
+[`unregisterObject()`](#api.unregister.object) and [objects
+page](#advanced.features.objects)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-template-vars.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-template-vars.md
new file mode 100644
index 0000000..27882ee
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-get-template-vars.md
@@ -0,0 +1,37 @@
+getTemplateVars()
+
+returns assigned variable value(s)
+
+Description
+===========
+
+array
+
+getTemplateVars
+
+string
+
+varname
+
+If no parameter is given, an array of all [assigned](#api.assign)
+variables are returned.
+
+
+ getTemplateVars('foo');
+
+ // get all assigned template vars
+ $all_tpl_vars = $smarty->getTemplateVars();
+
+ // take a look at them
+ print_r($all_tpl_vars);
+ ?>
+
+
+
+See also [`assign()`](#api.assign),
+[`{assign}`](#language.function.assign), [`append()`](#api.append),
+[`clearAssign()`](#api.clear.assign),
+[`clearAllAssign()`](#api.clear.all.assign) and
+[`getConfigVars()`](#api.get.config.vars)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-is-cached.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-is-cached.md
new file mode 100644
index 0000000..d9d3057
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-is-cached.md
@@ -0,0 +1,81 @@
+isCached()
+
+returns true if there is a valid cache for this template
+
+Description
+===========
+
+bool
+
+isCached
+
+string
+
+template
+
+string
+
+cache\_id
+
+string
+
+compile\_id
+
+- This only works if [`$caching`](#variable.caching) is set to one of
+ `\Smarty\Smarty::CACHING_LIFETIME_CURRENT` or
+ `\Smarty\Smarty::CACHING_LIFETIME_SAVED` to enable caching. See the [caching
+ section](#caching) for more info.
+
+- You can also pass a `$cache_id` as an optional second parameter in
+ case you want [multiple caches](#caching.multiple.caches) for the
+ given template.
+
+- You can supply a [`$compile id`](#variable.compile.id) as an
+ optional third parameter. If you omit that parameter the persistent
+ [`$compile_id`](#variable.compile.id) is used if its set.
+
+- If you do not want to pass a `$cache_id` but want to pass a
+ [`$compile_id`](#variable.compile.id) you have to pass NULL as a
+ `$cache_id`.
+
+> **Note**
+>
+> If `isCached()` returns TRUE it actually loads the cached output and
+> stores it internally. Any subsequent call to
+> [`display()`](#api.display) or [`fetch()`](#api.fetch) will return
+> this internally stored output and does not try to reload the cache
+> file. This prevents a race condition that may occur when a second
+> process clears the cache between the calls to `isCached()` and to
+> [`display()`](#api.display) in the example above. This also means
+> calls to [`clearCache()`](#api.clear.cache) and other changes of the
+> cache-settings may have no effect after `isCached()` returned TRUE.
+
+
+ setCaching(Smarty::CACHING_LIFETIME_CURRENT);
+
+ if(!$smarty->isCached('index.tpl')) {
+ // do database calls, assign vars here
+ }
+
+ $smarty->display('index.tpl');
+ ?>
+
+
+
+
+ setCaching(Smarty::CACHING_LIFETIME_CURRENT);
+
+ if(!$smarty->isCached('index.tpl', 'FrontPage')) {
+ // do database calls, assign vars here
+ }
+
+ $smarty->display('index.tpl', 'FrontPage');
+ ?>
+
+
+
+See also [`clearCache()`](#api.clear.cache),
+[`clearAllCache()`](#api.clear.all.cache), and [caching
+section](#caching).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-load-filter.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-load-filter.md
new file mode 100644
index 0000000..e2738b0
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-load-filter.md
@@ -0,0 +1,41 @@
+loadFilter()
+
+load a filter plugin
+
+Description
+===========
+
+void
+
+loadFilter
+
+string
+
+type
+
+string
+
+name
+
+The first argument specifies the type of the filter to load and can be
+one of the following: `variable`, `pre`, `post` or `output`. The second argument
+specifies the `name` of the filter plugin.
+
+
+ loadFilter('pre', 'trim');
+
+ // load another prefilter named 'datefooter'
+ $smarty->loadFilter('pre', 'datefooter');
+
+ // load output filter named 'compress'
+ $smarty->loadFilter('output', 'compress');
+
+ ?>
+
+
+
+See also [`registerFilter()`](#api.register.filter) and [advanced
+features](#advanced.features).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-mute-expected-errors.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-mute-expected-errors.md
new file mode 100644
index 0000000..ac84a64
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-mute-expected-errors.md
@@ -0,0 +1,21 @@
+Smarty::muteExpectedErrors()
+
+mutes expected warnings and notices deliberately generated by Smarty
+
+Description
+===========
+
+string
+
+muteExpectedErrors
+
+muteExpectedErrors() registers a custom error handler using
+[set\_error\_handler()](https://www.php.net/set_error_handler). The error
+handler merely inspects `$errno` and `$errfile` to determine if the
+given error was produced deliberately and must be ignored, or should be
+passed on to the next error handler.
+
+`\Smarty\Smarty::unmuteExpectedErrors()` removes the current error handler.
+Please note, that if you\'ve registered any custom error handlers after
+the muteExpectedErrors() call, the unmute will not remove Smarty\'s
+muting error handler, but the one registered last.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-cacheresource.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-cacheresource.md
new file mode 100644
index 0000000..6260914
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-cacheresource.md
@@ -0,0 +1,40 @@
+registerCacheResource()
+
+dynamically register CacheResources
+
+Description
+===========
+
+void
+
+registerCacheResource
+
+string
+
+name
+
+Smarty\_CacheResource
+
+resource\_handler
+
+Use this to dynamically register a [CacheResource
+plugin](#caching.custom) with Smarty. Pass in the `name` of the
+CacheResource and the object extending Smarty\_CacheResource. See
+[Custom Cache Implementation](#caching.custom) for more information on
+how to create custom CacheResources.
+
+> **Note**
+>
+> In Smarty2 this used to be a callback function called
+> `$cache_handler_func`. Smarty3 replaced this callback by the
+> `Smarty_CacheResource` module.
+
+
+ registerCacheResource('mysql', new My_CacheResource_Mysql());
+ ?>
+
+
+
+See also [`unregisterCacheResource()`](#api.unregister.cacheresource)
+and the [Custom CacheResource Implementation](#caching.custom) section.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-class.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-class.md
new file mode 100644
index 0000000..d0156d5
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-class.md
@@ -0,0 +1,68 @@
+registerClass()
+
+register a class for use in the templates
+
+Description
+===========
+
+void
+
+registerClass
+
+string
+
+class\_name
+
+string
+
+class\_impl
+
+Smarty allows you to access static classes from templates as long as the
+[Security Policy](#advanced.features.security) does not tell it
+otherwise. If security is enabled, classes registered with
+`registerClass()` are accessible to templates.
+
+
+ registerClass("Foo", "Bar");
+
+
+
+
+ {* Smarty will access this class as long as it's not prohibited by security *}
+ {Bar::$property}
+ {* Foo translates to the real class Bar *}
+ {Foo::$property}
+
+
+
+
+ registerClass("Foo", "\my\php\application\Bar");
+
+
+
+
+ {* Foo translates to the real class \my\php\application\Bar *}
+ {Foo::$property}
+
+
+
+See also [`registerObject()`](#api.register.object), and
+[Security](#advanced.features.security).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-default-plugin-handler.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-default-plugin-handler.md
new file mode 100644
index 0000000..61ac476
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-default-plugin-handler.md
@@ -0,0 +1,93 @@
+registerDefaultPluginHandler()
+
+register a function which gets called on undefined tags
+
+Description
+===========
+
+void
+
+registerDefaultPluginHandler
+
+mixed
+
+callback
+
+Register a default plugin handler which gets called if the compiler can
+not find a definition for a tag otherwise. It uses the following
+parameters:
+
+If during compilation Smarty encounters tag which is not defined
+internal, registered or located in the plugins folder it tries to
+resolve it by calling the registered default plugin handler. The handler
+may be called several times for same undefined tag looping over valid
+plugin types.
+
+
+ registerDefaultPluginHandler('my_plugin_handler');
+
+ /**
+ * Default Plugin Handler
+ *
+ * called when Smarty encounters an undefined tag during compilation
+ *
+ * @param string $name name of the undefined tag
+ * @param string $type tag type (e.g. Smarty::PLUGIN_FUNCTION, Smarty::PLUGIN_BLOCK,
+ Smarty::PLUGIN_COMPILER, Smarty::PLUGIN_MODIFIER, Smarty::PLUGIN_MODIFIERCOMPILER)
+ * @param \Smarty\Template\ $template template object
+ * @param string &$callback returned function name
+ * @param string &$script optional returned script filepath if function is external
+ * @param bool &$cacheable true by default, set to false if plugin is not cachable (Smarty >= 3.1.8)
+ * @return bool true if successfull
+ */
+ function my_plugin_handler ($name, $type, $template, &$callback, &$script, &$cacheable)
+ {
+ switch ($type) {
+ case Smarty::PLUGIN_FUNCTION:
+ switch ($name) {
+ case 'scriptfunction':
+ $script = './scripts/script_function_tag.php';
+ $callback = 'default_script_function_tag';
+ return true;
+ case 'localfunction':
+ $callback = 'default_local_function_tag';
+ return true;
+ default:
+ return false;
+ }
+ case Smarty::PLUGIN_COMPILER:
+ switch ($name) {
+ case 'scriptcompilerfunction':
+ $script = './scripts/script_compiler_function_tag.php';
+ $callback = 'default_script_compiler_function_tag';
+ return true;
+ default:
+ return false;
+ }
+ case Smarty::PLUGIN_BLOCK:
+ switch ($name) {
+ case 'scriptblock':
+ $script = './scripts/script_block_tag.php';
+ $callback = 'default_script_block_tag';
+ return true;
+ default:
+ return false;
+ }
+ default:
+ return false;
+ }
+ }
+
+ ?>
+
+
+
+> **Note**
+>
+> The return callback must be static; a function name or an array of
+> class and method name.
+>
+> Dynamic callbacks like objects methods are not supported.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-filter.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-filter.md
new file mode 100644
index 0000000..4a2aa4b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-filter.md
@@ -0,0 +1,44 @@
+registerFilter()
+
+dynamically register filters
+
+Description
+===========
+
+void
+
+registerFilter
+
+string
+
+type
+
+mixed
+
+callback
+
+Use this to dynamically register filters to operate on a templates. It
+uses the following parameters:
+
+NOTE.PARAMETER.FUNCTION
+
+A [prefilter](#plugins.prefilters.postfilters) runs through the template
+source before it gets compiled. See [template
+prefilters](#advanced.features.prefilters) for more information on how
+to setup a prefiltering function.
+
+A [postfilter](#plugins.prefilters.postfilters) runs through the
+template code after it was compiled to PHP. See [template
+postfilters](#advanced.features.postfilters) for more information on how
+to setup a postfiltering function.
+
+A [outputfilter](#plugins.outputfilters) operates on a template\'s
+output before it is [displayed](#api.display). See [template output
+filters](#advanced.features.outputfilters) for more information on how
+to set up an output filter function.
+
+See also [`unregisterFilter()`](#api.unregister.filter),
+[`loadFilter()`](#api.load.filter), [template pre
+filters](#advanced.features.prefilters) [template post
+filters](#advanced.features.postfilters) [template output
+filters](#advanced.features.outputfilters) section.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-object.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-object.md
new file mode 100644
index 0000000..c310e8c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-object.md
@@ -0,0 +1,44 @@
+registerObject()
+
+register an object for use in the templates
+
+Description
+===========
+
+void
+
+registerObject
+
+string
+
+object\_name
+
+object
+
+object
+
+array
+
+allowed\_methods\_properties
+
+boolean
+
+format
+
+array
+
+block\_methods
+
+> **Note**
+>
+> When you register/assign objects to templates, be sure that all
+> properties and methods accessed from the template are for presentation
+> purposes only. It is very easy to inject application logic through
+> objects, and this leads to poor designs that are difficult to manage.
+> See the Best Practices section of the Smarty website.
+
+See the [objects section](#advanced.features.objects) for more
+information.
+
+See also [`getRegisteredObject()`](#api.get.registered.object), and
+[`unregisterObject()`](#api.unregister.object).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-plugin.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-plugin.md
new file mode 100644
index 0000000..51342b8
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-plugin.md
@@ -0,0 +1,110 @@
+registerPlugin()
+
+dynamically register plugins
+
+Description
+===========
+
+void
+
+registerPlugin
+
+string
+
+type
+
+string
+
+name
+
+mixed
+
+callback
+
+bool
+
+cacheable
+
+mixed
+
+cache\_attrs
+
+This method registers functions or methods defined in your script as
+plugin. It uses the following parameters:
+
+- `cacheable` can be omitted in most cases. See
+ [controlling cacheability of plugins output](#caching.cacheable) on
+ how to use this properly.
+
+
+
+
+ registerPlugin("function","date_now", "print_current_date");
+
+ function print_current_date($params, $smarty)
+ {
+ if(empty($params["format"])) {
+ $format = "%b %e, %Y";
+ } else {
+ $format = $params["format"];
+ }
+ return strftime($format,time());
+ }
+ ?>
+
+
+
+And in the template
+
+
+ {date_now}
+
+ {* or to format differently *}
+ {date_now format="%Y/%m/%d"}
+
+
+ registerPlugin("block","translate", "do_translation");
+ ?>
+
+
+
+Where the template is:
+
+
+ {translate lang="br"}Hello, world!{/translate}
+
+
+
+
+ registerPlugin("modifier","ss", "stripslashes");
+
+ ?>
+
+In the template, use `ss` to strip slashes.
+
+
+
+
+See also [`unregisterPlugin()`](#api.unregister.plugin), [plugin
+functions](#plugins.functions), [plugin block
+functions](#plugins.block.functions), [plugin compiler
+functions](#plugins.compiler.functions), and the [creating plugin
+modifiers](#plugins.modifiers) section.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-resource.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-resource.md
new file mode 100644
index 0000000..774452b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-register-resource.md
@@ -0,0 +1,46 @@
+registerResource()
+
+dynamically register resources
+
+Description
+===========
+
+void
+
+registerResource
+
+string
+
+name
+
+Smarty\_resource
+
+resource\_handler
+
+Use this to dynamically register a [Resource plugin](#resources) with
+Smarty. Pass in the `name` of the Resource and the object extending
+Smarty\_Resource. See [template resources](#resources) for more
+information on how to setup a function for fetching templates.
+
+> **Note**
+>
+> A resource name must be at least two characters in length. One
+> character resource names will be ignored and used as part of the file
+> path, such as `$smarty->display('c:/path/to/index.tpl');`
+
+> **Note**
+>
+> Prior to Smarty 3.1 `registerResource()` accepted an array of callback
+> functions. While this is still possible for backward compatibility
+> reasons, it is strongly discouraged as callback functions have been
+> deprecated as of Smarty 3.1.
+
+
+ registerResource('mysql', new My_Resource_Mysql());
+ ?>
+
+
+
+See also [`unregisterResource()`](#api.unregister.resource) and the
+[template resources](#resources) section.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-set-plugins-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-set-plugins-dir.md
new file mode 100644
index 0000000..25b0567
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-set-plugins-dir.md
@@ -0,0 +1,46 @@
+setPluginsDir()
+
+set the directories where plugins are stored
+
+Description
+===========
+
+Smarty
+
+setPluginsDir
+
+string\|array
+
+plugins\_dir
+
+
+ setPluginsDir('./plugins');
+
+ // view the plugins dir chain
+ var_dump($smarty->getPluginsDir());
+
+ // set multiple directoríes where plugins are stored
+ $smarty->setPluginsDir(array(
+ './plugins',
+ './plugins_2',
+ ));
+
+ // view the plugins dir chain
+ var_dump($smarty->getPluginsDir());
+
+ // chaining of method calls
+ $smarty->setTemplateDir('./templates')
+ ->setPluginsDir('./plugins')
+ ->setCompileDir('./templates_c')
+ ->setCacheDir('./cache');
+
+ ?>
+
+
+
+See also [`getPluginsDir()`](#api.get.plugins.dir),
+[`addPluginsDir()`](#api.add.plugins.dir) and
+[`$plugins_dir`](#variable.plugins.dir).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-test-install.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-test-install.md
new file mode 100644
index 0000000..bba64a1
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-test-install.md
@@ -0,0 +1,22 @@
+testInstall()
+
+checks Smarty installation
+
+Description
+===========
+
+void
+
+testInstall
+
+This function verifies that all required working folders of the Smarty
+installation can be accessed. It does output a corresponding protocol.
+
+
+ testInstall();
+ ?>
+
+
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-cacheresource.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-cacheresource.md
new file mode 100644
index 0000000..d097519
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-cacheresource.md
@@ -0,0 +1,28 @@
+unregisterCacheResource()
+
+dynamically unregister a CacheResource plugin
+
+Description
+===========
+
+void
+
+unregisterCacheResource
+
+string
+
+name
+
+Pass in the `name` of the CacheResource.
+
+
+ unregisterCacheResource('mysql');
+
+ ?>
+
+
+
+See also [`registerCacheResource()`](#api.register.cacheresource) and
+the [Custom CacheResource Implementation](#caching.custom) section.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-filter.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-filter.md
new file mode 100644
index 0000000..44020eb
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-filter.md
@@ -0,0 +1,23 @@
+unregisterFilter()
+
+dynamically unregister a filter
+
+Description
+===========
+
+void
+
+unregisterFilter
+
+string
+
+type
+
+string\|array
+
+callback
+
+Use this to dynamically unregister filters. It uses the following
+parameters:
+
+See also [`registerFilter()`](#api.register.filter).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-object.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-object.md
new file mode 100644
index 0000000..c012581
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-object.md
@@ -0,0 +1,17 @@
+unregisterObject()
+
+dynamically unregister an object
+
+Description
+===========
+
+void
+
+unregisterObject
+
+string
+
+object\_name
+
+See also [`registerObject()`](#api.register.object) and [objects
+section](#advanced.features.objects)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-plugin.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-plugin.md
new file mode 100644
index 0000000..c692ac6
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-plugin.md
@@ -0,0 +1,36 @@
+unregisterPlugin
+
+dynamically unregister plugins
+
+Description
+===========
+
+void
+
+unregisterPlugin
+
+string
+
+type
+
+string
+
+name
+
+This method unregisters plugins which previously have been registered by
+[registerPlugin()](#api.register.plugin), It uses the following
+parameters:
+
+
+
+
+ unregisterPlugin("function","date_now");
+
+ ?>
+
+
+
+See also [`registerPlugin()`](#api.register.plugin).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-resource.md b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-resource.md
new file mode 100644
index 0000000..1a6067b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-functions/api-unregister-resource.md
@@ -0,0 +1,28 @@
+unregisterResource()
+
+dynamically unregister a resource plugin
+
+Description
+===========
+
+void
+
+unregisterResource
+
+string
+
+name
+
+Pass in the `name` of the resource.
+
+
+ unregisterResource('db');
+
+ ?>
+
+
+
+See also [`registerResource()`](#api.register.resource) and [template
+resources](#resources)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-auto-literal.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-auto-literal.md
new file mode 100644
index 0000000..8d06850
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-auto-literal.md
@@ -0,0 +1,17 @@
+\$auto\_literal {#variable.auto.literal}
+===============
+
+The Smarty delimiter tags { and } will be ignored so long as they are
+surrounded by white space. This behavior can be disabled by setting
+auto\_literal to false.
+
+::: {.informalexample}
+
+ auto_literal = false;
+ ?>
+
+
+:::
+
+See also [Escaping Smarty parsing](#language.escaping),
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-dir.md
new file mode 100644
index 0000000..6cb2b55
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-dir.md
@@ -0,0 +1,35 @@
+\$cache\_dir {#variable.cache.dir}
+============
+
+This is the name of the directory where template caches are stored. By
+default this is `./cache`, meaning that Smarty will look for the
+`cache/` directory in the same directory as the executing php script.
+**This directory must be writeable by the web server**, [see
+install](#installing.smarty.basic) for more info.
+
+You can also use your own [custom cache implementation](#caching.custom)
+to control cache files, which will ignore this setting. See also
+[`$use_sub_dirs`](#variable.use.sub.dirs).
+
+> **Note**
+>
+> This setting must be either a relative or absolute path. include\_path
+> is not used for writing files.
+
+> **Note**
+>
+> It is not recommended to put this directory under the web server
+> document root.
+
+> **Note**
+>
+> As of Smarty 3.1 the attribute \$cache\_dir is no longer accessible
+> directly. Use [`getCacheDir()`](#api.get.cache.dir) and
+> [`setCacheDir()`](#api.set.cache.dir) instead.
+
+See also [`getCacheDir()`](#api.get.cache.dir),
+[`setCacheDir()`](#api.set.cache.dir), [`$caching`](#variable.caching),
+[`$use_sub_dirs`](#variable.use.sub.dirs),
+[`$cache_lifetime`](#variable.cache.lifetime),
+[`$cache_modified_check`](#variable.cache.modified.check) and the
+[caching section](#caching).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-id.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-id.md
new file mode 100644
index 0000000..c27fae9
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-id.md
@@ -0,0 +1,11 @@
+\$cache\_id {#variable.cache.id}
+===========
+
+Persistent cache\_id identifier. As an alternative to passing the same
+`$cache_id` to each and every function call, you can set this
+`$cache_id` and it will be used implicitly thereafter.
+
+With a `$cache_id` you can have multiple cache files for a single call
+to [`display()`](#api.display) or [`fetch()`](#api.fetch) depending for
+example from different content of the same template. See the [caching
+section](#caching) for more information.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-lifetime.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-lifetime.md
new file mode 100644
index 0000000..481fbee
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-lifetime.md
@@ -0,0 +1,30 @@
+\$cache\_lifetime {#variable.cache.lifetime}
+=================
+
+This is the length of time in seconds that a template cache is valid.
+Once this time has expired, the cache will be regenerated.
+
+- `$caching` must be turned on (either
+ \Smarty\Smarty::CACHING\_LIFETIME\_CURRENT or
+ \Smarty\Smarty::CACHING\_LIFETIME\_SAVED) for `$cache_lifetime` to have any
+ purpose.
+
+- A `$cache_lifetime` value of -1 will force the cache to never
+ expire.
+
+- A value of 0 will cause the cache to always regenerate (good for
+ testing only, to disable caching a more efficient method is to set
+ [`$caching`](#variable.caching) = \Smarty\Smarty::CACHING\_OFF).
+
+- If you want to give certain templates their own cache lifetime, you
+ could do this by setting [`$caching`](#variable.caching) =
+ \Smarty\Smarty::CACHING\_LIFETIME\_SAVED, then set `$cache_lifetime` to a
+ unique value just before calling [`display()`](#api.display) or
+ [`fetch()`](#api.fetch).
+
+If [`$force_compile`](#variable.force.compile) is enabled, the cache
+files will be regenerated every time, effectively disabling caching. You
+can clear all the cache files with the
+[`clear_all_cache()`](#api.clear.all.cache) function, or individual
+cache files (or groups) with the [`clear_cache()`](#api.clear.cache)
+function.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-locking.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-locking.md
new file mode 100644
index 0000000..6dca30c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-locking.md
@@ -0,0 +1,11 @@
+\$cache\_locking {#variable.cache.locking}
+================
+
+Cache locking avoids concurrent cache generation. This means resource
+intensive pages can be generated only once, even if they\'ve been
+requested multiple times in the same moment.
+
+Cache locking is disabled by default. To enable it set `$cache_locking`
+to TRUE.
+
+See also [`$locking_timeout`](#variable.locking.timeout)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-modified-check.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-modified-check.md
new file mode 100644
index 0000000..815be25
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-cache-modified-check.md
@@ -0,0 +1,11 @@
+\$cache\_modified\_check {#variable.cache.modified.check}
+========================
+
+If set to TRUE, Smarty will respect the If-Modified-Since header sent
+from the client. If the cached file timestamp has not changed since the
+last visit, then a `'304: Not Modified'` header will be sent instead of
+the content.
+
+See also [`$caching`](#variable.caching),
+[`$cache_lifetime`](#variable.cache.lifetime), and the [caching
+section](#caching).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-caching-type.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-caching-type.md
new file mode 100644
index 0000000..22b88cf
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-caching-type.md
@@ -0,0 +1,9 @@
+\$caching\_type {#variable.caching.type}
+===============
+
+This property specifies the name of the caching handler to use. It
+defaults to `file`, enabling the internal filesystem based cache
+handler.
+
+See [Custom Cache Implementation](#caching.custom) for pointers on
+setting up your own cache handler.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-caching.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-caching.md
new file mode 100644
index 0000000..7304e41
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-caching.md
@@ -0,0 +1,38 @@
+\$caching {#variable.caching}
+=========
+
+This tells Smarty whether or not to cache the output of the templates to
+the [`$cache_dir`](#variable.cache.dir). By default this is set to the
+constant \Smarty\Smarty::CACHING\_OFF. If your templates consistently generate
+the same content, it is advisable to turn on `$caching`, as this may
+result in significant performance gains.
+
+You can also have [multiple](#caching.multiple.caches) caches for the
+same template.
+
+- A constant value of \Smarty\Smarty::CACHING\_LIFETIME\_CURRENT or
+ \Smarty\Smarty ::CACHING\_LIFETIME\_SAVED enables caching.
+
+- A value of \Smarty\Smarty::CACHING\_LIFETIME\_CURRENT tells Smarty to use
+ the current [`$cache_lifetime`](#variable.cache.lifetime) variable
+ to determine if the cache has expired.
+
+- A value of \Smarty\Smarty::CACHING\_LIFETIME\_SAVED tells Smarty to use the
+ [`$cache_lifetime`](#variable.cache.lifetime) value at the time the
+ cache was generated. This way you can set the
+ [`$cache_lifetime`](#variable.cache.lifetime) just before
+ [fetching](#api.fetch) the template to have granular control over
+ when that particular cache expires. See also
+ [`isCached()`](#api.is.cached).
+
+- If [`$compile_check`](#variable.compile.check) is enabled, the
+ cached content will be regenerated if any of the templates or config
+ files that are part of this cache are changed.
+
+- If [`$force_compile`](#variable.force.compile) is enabled, the
+ cached content will always be regenerated.
+
+See also [`$cache_dir`](#variable.cache.dir),
+[`$cache_lifetime`](#variable.cache.lifetime),
+[`$cache_modified_check`](#variable.cache.modified.check),
+[`is_cached()`](#api.is.cached) and the [caching section](#caching).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-dir.md
new file mode 100644
index 0000000..c18c9ac
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-dir.md
@@ -0,0 +1,29 @@
+\$compile\_dir {#variable.compile.dir}
+==============
+
+This is the name of the directory where compiled templates are located.
+By default this is `./templates_c`, meaning that Smarty will look for
+the `templates_c/` directory in the same directory as the executing php
+script. **This directory must be writeable by the web server**, [see
+install](#installing.smarty.basic) for more info.
+
+> **Note**
+>
+> This setting must be either a relative or absolute path. include\_path
+> is not used for writing files.
+
+> **Note**
+>
+> It is not recommended to put this directory under the web server
+> document root.
+
+> **Note**
+>
+> As of Smarty 3.1 the attribute \$compile\_dir is no longer accessible
+> directly. Use [`getCompileDir()`](#api.get.compile.dir) and
+> [`setCompileDir()`](#api.set.compile.dir) instead.
+
+See also [`getCompileDir()`](#api.get.compile.dir),
+[`setCompileDir()`](#api.set.compile.dir),
+[`$compile_id`](#variable.compile.id) and
+[`$use_sub_dirs`](#variable.use.sub.dirs).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-id.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-id.md
new file mode 100644
index 0000000..ca2b08f
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-id.md
@@ -0,0 +1,44 @@
+\$compile\_id {#variable.compile.id}
+=============
+
+Persistent compile identifier. As an alternative to passing the same
+`$compile_id` to each and every function call, you can set this
+`$compile_id` and it will be used implicitly thereafter.
+
+If you use the same template with different [pre- and/or
+post-filters](#plugins.prefilters.postfilters) you must use a unique
+`$compile_id` to keep the compiled template files separated.
+
+For example a [prefilter](#plugins.prefilters.postfilters) that
+localizes your templates (that is: translates language dependent parts)
+at compile time, then you could use the current language as
+`$compile_id` and you will get a set of compiled templates for each
+language you use.
+
+
+ compile_id = 'en';
+ ?>
+
+
+
+Another application would be to use the same compile directory across
+multiple domains / multiple virtual hosts.
+
+
+ compile_id = $_SERVER['SERVER_NAME'];
+ $smarty->compile_dir = '/path/to/shared_compile_dir';
+
+ ?>
+
+
+
+> **Note**
+>
+> In Smarty 3 a `$compile_id` is no longer required to keep templates
+> with same name in different [`$template_dir`
+> folders](#variable.template.dir) separated. The [`$template_dir` file
+> path](#variable.template.dir) is encoded in the file name of compiled
+> and cached template files.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-locking.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-locking.md
new file mode 100644
index 0000000..ff7a66f
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compile-locking.md
@@ -0,0 +1,7 @@
+\$compile\_locking {#variable.compile.locking}
+==================
+
+Compile locking avoids concurrent compilation of the same template.
+
+Compile locking is enabled by default. To disable it set
+`$compile_locking` to FALSE.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compiler-class.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compiler-class.md
new file mode 100644
index 0000000..32ea982
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-compiler-class.md
@@ -0,0 +1,6 @@
+\$compiler\_class {#variable.compiler.class}
+=================
+
+Specifies the name of the compiler class that Smarty will use to compile
+the templates. The default is \'Smarty\_Compiler\'. For advanced users
+only.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-booleanize.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-booleanize.md
new file mode 100644
index 0000000..4ba555f
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-booleanize.md
@@ -0,0 +1,8 @@
+\$config\_booleanize {#variable.config.booleanize}
+====================
+
+If set to TRUE, [config files](#config.files) values of `on/true/yes`
+and `off/false/no` get converted to boolean values automatically. This
+way you can use the values in the template like so:
+`{if #foobar#}...{/if}`. If foobar was `on`, `true` or `yes`, the `{if}`
+statement will execute. Defaults to TRUE.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-dir.md
new file mode 100644
index 0000000..d73f327
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-dir.md
@@ -0,0 +1,23 @@
+\$config\_dir {#variable.config.dir}
+=============
+
+This is the directory used to store [config files](#config.files) used
+in the templates. Default is `./configs`, meaning that Smarty will look
+for the `configs/` directory in the same directory as the executing php
+script.
+
+> **Note**
+>
+> It is not recommended to put this directory under the web server
+> document root.
+
+> **Note**
+>
+> As of Smarty 3.1 the attribute \$config\_dir is no longer accessible
+> directly. Use [`getConfigDir()`](#api.get.config.dir),
+> [`setConfigDir()`](#api.set.config.dir) and
+> [`addConfigDir()`](#api.add.config.dir) instead.
+
+See also [`getConfigDir()`](#api.get.config.dir),
+[`setConfigDir()`](#api.set.config.dir) and
+[`addConfigDir()`](#api.add.config.dir).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-overwrite.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-overwrite.md
new file mode 100644
index 0000000..0b89683
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-overwrite.md
@@ -0,0 +1,40 @@
+\$config\_overwrite {#variable.config.overwrite}
+===================
+
+If set to TRUE, the default then variables read in from [config
+files](#config.files) will overwrite each other. Otherwise, the
+variables will be pushed onto an array. This is helpful if you want to
+store arrays of data in config files, just list each element multiple
+times.
+
+This examples uses [`{cycle}`](#language.function.cycle) to output a
+table with alternating red/green/blue row colors with
+`$config_overwrite` = FALSE.
+
+The config file.
+
+
+ # row colors
+ rowColors = #FF0000
+ rowColors = #00FF00
+ rowColors = #0000FF
+
+
+
+The template with a [`{section}`](#language.function.section) loop.
+
+
+
+ {section name=r loop=$rows}
+
+ ....etc....
+
+ {/section}
+
+
+
+
+See also [`{config_load}`](#language.function.config.load),
+[`getConfigVars()`](#api.get.config.vars),
+[`clearConfig()`](#api.clear.config), [`configLoad()`](#api.config.load)
+and the [config files section](#config.files).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-read-hidden.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-read-hidden.md
new file mode 100644
index 0000000..19cde68
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-config-read-hidden.md
@@ -0,0 +1,8 @@
+\$config\_read\_hidden {#variable.config.read.hidden}
+======================
+
+If set to TRUE, hidden sections ie section names beginning with a
+period(.) in [config files](#config.files) can be read from templates.
+Typically you would leave this FALSE, that way you can store sensitive
+data in the config files such as database parameters and not worry about
+the template loading them. FALSE by default.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debug-template.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debug-template.md
new file mode 100644
index 0000000..11a8052
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debug-template.md
@@ -0,0 +1,8 @@
+\$debug\_tpl {#variable.debug_template}
+============
+
+This is the name of the template file used for the debugging console. By
+default, it is named `debug.tpl` and is located in `src/debug.tpl`.
+
+See also [`$debugging`](#variable.debugging) and the [debugging
+console](#chapter.debugging.console) section.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debugging-ctrl.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debugging-ctrl.md
new file mode 100644
index 0000000..a9355c0
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debugging-ctrl.md
@@ -0,0 +1,20 @@
+\$debugging\_ctrl {#variable.debugging.ctrl}
+=================
+
+This allows alternate ways to enable debugging. `NONE` means no
+alternate methods are allowed. `URL` means when the keyword
+`SMARTY_DEBUG` is found in the `QUERY_STRING`, debugging is enabled for
+that invocation of the script. If [`$debugging`](#variable.debugging) is
+TRUE, this value is ignored.
+
+
+ debugging = false; // the default
+ $smarty->debugging_ctrl = ($_SERVER['SERVER_NAME'] == 'localhost') ? 'URL' : 'NONE';
+ ?>
+
+See also [debugging console](#chapter.debugging.console) section,
+[`$debugging`](#variable.debugging) and
+[`$smarty_debug_id`](#variable.smarty.debug.id).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debugging.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debugging.md
new file mode 100644
index 0000000..4473e0c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-debugging.md
@@ -0,0 +1,17 @@
+\$debugging {#variable.debugging}
+===========
+
+This enables the [debugging console](#chapter.debugging.console). The
+console is a javascript popup window that informs you of the
+[included](#language.function.include) templates, variables
+[assigned](#api.assign) from php and [config file
+variables](#language.config.variables) for the current script. It does
+not show variables assigned within a template with the
+[`{assign}`](#language.function.assign) function.
+
+The console can also be enabled from the url with
+[`$debugging_ctrl`](#variable.debugging.ctrl).
+
+See also [`{debug}`](#language.function.debug),
+[`$debug_tpl`](#variable.debug_template), and
+[`$debugging_ctrl`](#variable.debugging.ctrl).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-config-handler-func.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-config-handler-func.md
new file mode 100644
index 0000000..50eb65b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-config-handler-func.md
@@ -0,0 +1,50 @@
+\$default\_config\_handler\_func {#variable.default.config.handler.func}
+================================
+
+This function is called when a config file cannot be obtained from its
+resource.
+
+> **Note**
+>
+> The default handler is currently only invoked for file resources. It
+> is not triggered when the resource itself cannot be found, in which
+> case a \Smarty\Exception is thrown.
+
+
+ default_config_handler_func = 'my_default_config_handler_func';
+
+ /**
+ * Default Config Handler
+ *
+ * called when Smarty's file: resource is unable to load a requested file
+ *
+ * @param string $type resource type (e.g. "file", "string", "eval", "resource")
+ * @param string $name resource name (e.g. "foo/bar.tpl")
+ * @param string &$content config's content
+ * @param integer &$modified config's modification time
+ * @param Smarty $smarty Smarty instance
+ * @return string|boolean path to file or boolean true if $content and $modified
+ * have been filled, boolean false if no default config
+ * could be loaded
+ */
+ function my_default_config_handler_func($type, $name, &$content, &$modified, Smarty $smarty) {
+ if (false) {
+ // return corrected filepath
+ return "/tmp/some/foobar.tpl";
+ } elseif (false) {
+ // return a config directly
+ $content = 'someVar = "the config source"';
+ $modified = time();
+ return true;
+ } else {
+ // tell smarty that we failed
+ return false;
+ }
+ }
+
+ ?>
+
+
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-config-type.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-config-type.md
new file mode 100644
index 0000000..60bf9f1
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-config-type.md
@@ -0,0 +1,7 @@
+\$default\_config\_type {#variable.default.config.type}
+=======================
+
+This tells smarty what resource type to use for config files. The
+default value is `file`, meaning that `$smarty->configLoad('test.conf')`
+and `$smarty->configLoad('file:test.conf')` are identical in meaning.
+See the [resource](#resources) chapter for more details.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-modifiers.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-modifiers.md
new file mode 100644
index 0000000..c6b73eb
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-modifiers.md
@@ -0,0 +1,8 @@
+\$default\_modifiers {#variable.default.modifiers}
+====================
+
+This is an array of modifiers to implicitly apply to every variable in a
+template. For example, to HTML-escape every variable by default, use
+`array('escape:"htmlall"')`. To make a variable exempt from default
+modifiers, add the \'nofilter\' attribute to the output tag such as
+`{$var nofilter}`.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-resource-type.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-resource-type.md
new file mode 100644
index 0000000..e8a8031
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-resource-type.md
@@ -0,0 +1,7 @@
+\$default\_resource\_type {#variable.default.resource.type}
+=========================
+
+This tells smarty what resource type to use implicitly. The default
+value is `file`, meaning that `$smarty->display('index.tpl')` and
+`$smarty->display('file:index.tpl')` are identical in meaning. See the
+[resource](#resources) chapter for more details.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-template-handler-func.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-template-handler-func.md
new file mode 100644
index 0000000..96c8190
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-default-template-handler-func.md
@@ -0,0 +1,50 @@
+\$default\_template\_handler\_func {#variable.default.template.handler.func}
+==================================
+
+This function is called when a template cannot be obtained from its
+resource.
+
+> **Note**
+>
+> The default handler is currently only invoked for file resources. It
+> is not triggered when the resource itself cannot be found, in which
+> case a \Smarty\Exception is thrown.
+
+
+ default_template_handler_func = 'my_default_template_handler_func';
+
+ /**
+ * Default Template Handler
+ *
+ * called when Smarty's file: resource is unable to load a requested file
+ *
+ * @param string $type resource type (e.g. "file", "string", "eval", "resource")
+ * @param string $name resource name (e.g. "foo/bar.tpl")
+ * @param string &$content template's content
+ * @param integer &$modified template's modification time
+ * @param Smarty $smarty Smarty instance
+ * @return string|boolean path to file or boolean true if $content and $modified
+ * have been filled, boolean false if no default template
+ * could be loaded
+ */
+ function my_default_template_handler_func($type, $name, &$content, &$modified, Smarty $smarty) {
+ if (false) {
+ // return corrected filepath
+ return "/tmp/some/foobar.tpl";
+ } elseif (false) {
+ // return a template directly
+ $content = "the template source";
+ $modified = time();
+ return true;
+ } else {
+ // tell smarty that we failed
+ return false;
+ }
+ }
+
+ ?>
+
+
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-error-reporting.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-error-reporting.md
new file mode 100644
index 0000000..ee28d47
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-error-reporting.md
@@ -0,0 +1,17 @@
+\$error\_reporting {#variable.error.reporting}
+==================
+
+When this value is set to a non-null-value it\'s value is used as php\'s
+[`error_reporting`](https://www.php.net/error_reporting) level inside of
+[`display()`](#api.display) and [`fetch()`](#api.fetch).
+
+Smarty 3.1.2 introduced the
+[`muteExpectedErrors()`](#api.mute.expected.errors) function. Calling
+`\Smarty\Smarty::muteExpectedErrors();` after setting up custom error handling
+will ensure that warnings and notices (deliberately) produced by Smarty
+will not be passed to other custom error handlers. If your error logs
+are filling up with warnings regarding `filemtime()` or `unlink()`
+calls, please enable Smarty\'s error muting.
+
+See also [debugging](#chapter.debugging.console) and
+[troubleshooting](#troubleshooting).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-escape-html.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-escape-html.md
new file mode 100644
index 0000000..87c7b96
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-escape-html.md
@@ -0,0 +1,21 @@
+\$escape\_html {#variable.escape.html}
+==============
+
+Setting `$escape_html` to TRUE will escape all template variable output
+by wrapping it in
+`htmlspecialchars({$output}, ENT_QUOTES, $char_set);`,
+which is the same as `{$variable|escape:"html"}`.
+
+Template designers can choose to selectively disable this feature by
+adding the `nofilter` flag: `{$variable nofilter}`.
+
+Modifiers and Filters are run in the following order: modifier,
+default\_modifier, \$escape\_html, registered variable filters,
+autoloaded variable filters, template instance\'s variable filters.
+Everything except the individual modifier can be disabled with the
+`nofilter` flag.
+
+> **Note**
+>
+> This is a compile time option. If you change the setting you must make
+> sure that the templates get recompiled.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-force-cache.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-force-cache.md
new file mode 100644
index 0000000..de0c0c1
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-force-cache.md
@@ -0,0 +1,6 @@
+\$force\_cache {#variable.force.cache}
+==============
+
+This forces Smarty to (re)cache templates on every invocation. It does
+not override the [`$caching`](#variable.caching) level, but merely
+pretends the template has never been cached before.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-force-compile.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-force-compile.md
new file mode 100644
index 0000000..73f1e79
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-force-compile.md
@@ -0,0 +1,9 @@
+\$force\_compile {#variable.force.compile}
+================
+
+This forces Smarty to (re)compile templates on every invocation. This
+setting overrides [`$compile_check`](#variable.compile.check). By
+default this is FALSE. This is handy for development and
+[debugging](#chapter.debugging.console). It should never be used in a
+production environment. If [`$caching`](#variable.caching) is enabled,
+the cache file(s) will be regenerated every time.
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-locking-timeout.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-locking-timeout.md
new file mode 100644
index 0000000..82fd056
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-locking-timeout.md
@@ -0,0 +1,7 @@
+\$locking\_timeout {#variable.locking.timeout}
+==================
+
+This is maximum time in seconds a cache lock is valid to avoid dead
+locks. The default value is 10 seconds.
+
+See also [`$cache_locking`](#variable.cache.locking)
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-merge-compiled-includes.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-merge-compiled-includes.md
new file mode 100644
index 0000000..8220c44
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-merge-compiled-includes.md
@@ -0,0 +1,27 @@
+\$merge\_compiled\_includes {#variable.merge.compiled.includes}
+===========================
+
+By setting `$merge_compiled_includes` to TRUE Smarty will merge the
+compiled template code of subtemplates into the compiled code of the
+main template. This increases rendering speed of templates using a many
+different sub-templates.
+
+Individual sub-templates can be merged by setting the `inline` option
+flag within the `{include}` tag. `$merge_compiled_includes` does not
+have to be enabled for the `inline` merge.
+
+::: {.informalexample}
+
+ merge_compiled_includes = true;
+ ?>
+
+
+:::
+
+> **Note**
+>
+> This is a compile time option. If you change the setting you must make
+> sure that the templates get recompiled.
+
+See also [`{include}`](#language.function.include) tag
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-smarty-debug-id.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-smarty-debug-id.md
new file mode 100644
index 0000000..0733ed5
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-smarty-debug-id.md
@@ -0,0 +1,9 @@
+\$smarty\_debug\_id {#variable.smarty.debug.id}
+===================
+
+The value of `$smarty_debug_id` defines the URL keyword to enable
+debugging at browser level. The default value is `SMARTY_DEBUG`.
+
+See also [debugging console](#chapter.debugging.console) section,
+[`$debugging`](#variable.debugging) and
+[`$debugging_ctrl`](#variable.debugging.ctrl).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-template-dir.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-template-dir.md
new file mode 100644
index 0000000..eb91d2c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-template-dir.md
@@ -0,0 +1,26 @@
+\$template\_dir {#variable.template.dir}
+===============
+
+This is the name of the default template directory. If you do not supply
+a resource type when including files, they will be found here. By
+default this is `./templates`, meaning that Smarty will look for the
+`templates/` directory in the same directory as the executing php
+script. \$template\_dir can also be an array of directory paths: Smarty
+will traverse the directories and stop on the first matching template
+found.
+
+> **Note**
+>
+> It is not recommended to put this directory under the web server
+> document root.
+
+> **Note**
+> As of Smarty 3.1 the attribute \$template\_dir is no longer accessible
+> directly. Use [`getTemplateDir()`](#api.get.template.dir),
+> [`setTemplateDir()`](#api.set.template.dir) and
+> [`addTemplateDir()`](#api.add.template.dir) instead.
+
+See also [`Template Resources`](#resources),
+[`getTemplateDir()`](#api.get.template.dir),
+[`setTemplateDir()`](#api.set.template.dir) and
+[`addTemplateDir()`](#api.add.template.dir).
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-use-include-path.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-use-include-path.md
new file mode 100644
index 0000000..e69de29
diff --git a/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-use-sub-dirs.md b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-use-sub-dirs.md
new file mode 100644
index 0000000..dcda3f2
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/programmers/api-variables/variable-use-sub-dirs.md
@@ -0,0 +1,31 @@
+\$use\_sub\_dirs {#variable.use.sub.dirs}
+================
+
+Smarty will create subdirectories under the [compiled
+templates](#variable.compile.dir) and [cache](#variable.cache.dir)
+directories if `$use_sub_dirs` is set to TRUE, default is FALSE. In an
+environment where there are potentially tens of thousands of files
+created, this may help the filesystem speed. On the other hand, some
+environments do not allow PHP processes to create directories, so this
+must be disabled which is the default.
+
+Sub directories are more efficient, so use them if you can.
+Theoretically you get much better performance on a filesystem with 10
+directories each having 100 files, than with 1 directory having 1000
+files. This was certainly the case with Solaris 7 (UFS)\... with newer
+filesystems such as ext3 and especially reiserfs, the difference is
+almost nothing.
+
+> **Note**
+>
+> - `$use_sub_dirs=true` doesn\'t work with
+> [safe\_mode=On](https://www.php.net/features.safe-mode), that\'s why
+> it\'s switchable and why it\'s off by default.
+>
+> - `$use_sub_dirs=true` on Windows can cause problems.
+>
+> - Safe\_mode is being deprecated in PHP6.
+>
+See also [`$compile_id`](#variable.compile.id),
+[`$cache_dir`](#variable.cache.dir), and
+[`$compile_dir`](#variable.compile.dir).
diff --git a/src/includes/smarty-5.4.1/docs/upgrading.md b/src/includes/smarty-5.4.1/docs/upgrading.md
new file mode 100644
index 0000000..ef9cc4c
--- /dev/null
+++ b/src/includes/smarty-5.4.1/docs/upgrading.md
@@ -0,0 +1,157 @@
+# Upgrading from an older version
+
+## Upgrading from v4 to v5
+
+Smarty 5 adds support for PHP8.2 and drops support for PHP7.1. Smarty also adds support for new features
+such as the ternary operator (`{$test ? $a : $b}` and `{$var ?: $value_if_falsy}`), the null coalescing operator (`{$var ?? $value_if_null}`)
+and positional parameters for custom tags.
+Smarty 5 also has a brand-new extension architecture that allows you to write neat extension packs.
+
+### Namespaces
+All Smarty code has been moved into the `\Smarty` namespace. This reduces
+the chance of conflicts with other (your) code.
+
+For simple use-cases, you only need to add `use Smarty\Smarty;` to your script and everything will work.
+
+```php
+display('homepage.tpl');
+```
+For more information, see [getting started](getting-started.md).
+
+If you extend Smarty or use Smarty plug-ins, please review your code to see if they assume specific class or method names.
+E.g.: `Smarty_Internal_Template` is now `\Smarty\Template\`, `SmartyException` is now `\Smarty\Exception`.
+
+### Variable scope bubbling
+Template variable scope bubbling has been simplified and made more consistent. The global scope now equals the Smarty
+scope in order to avoid global state side effects. Please read the [documentation on language variable scope](designers/language-variables/language-variable-scopes.md)
+for more details.
+
+Also, `{config_load}` no longer has a `scope` parameter, which means you can no longer load config
+from inside your template into the global scope (again, to avoid global state side effects). If you
+need to set global config, use the [configLoad API method](api/variables/config-files.md) from your PHP code.
+
+### Using native PHP-functions or userland functions in your templates
+You can no longer use native PHP-functions or userland functions in your templates without registering them.
+If you need a function in your templates, register it first.
+
+The easiest way to do so is as follows:
+```php
+// native PHP functions used as modifiers need to be registered
+$smarty->registerPlugin('modifier', 'substr', 'substr');
+
+// userland PHP functions used as modifiers need to be registered
+$smarty->registerPlugin('modifier', 'my_special_func', 'my_special_func');
+```
+
+But you may want to consider writing a proper [extension](api/extending/extensions.md).
+
+### Removed undocumented tags
+
+Smarty 4 still supported some tags that have been carried over from previous version, but have never been documented.
+
+- `{block_parent}` should be replaced with `{$smarty.block.parent}`
+- `{parent}` should be replaced with `{$smarty.block.parent}`
+- `{block_child}` should be replaced with `{$smarty.block.child}`
+- `{child}` should be replaced with `{$smarty.block.child}`
+
+- `{make_nocache}` is no longer supported
+- `{insert}` is no longer supported
+
+### Removed Smarty API properties
+
+In Smarty 4, you could make many configuration changes by directly accessing public properties on the Smarty object in PHP.
+In many cases, these properties have been made private, and you should now use the appropriate setter method:
+
+- `$smarty->left_delimiter` should be replaced with `$smarty->getLeftDelimiter()`/`$smarty->setLeftDelimiter()`
+- `$smarty->right_delimiter` should be replaced with `$smarty->getRightDelimiter()`/`$smarty->setRightDelimiter()`
+- `$smarty->autoload_filters` should be replaced with `$smarty->registerFilter()`
+- `$smarty->template_dir` should be replaced with `$smarty->setTemplateDir()`
+- `$smarty->cache_dir` should be replaced with `$smarty->setCacheDir()`
+- `$smarty->compile_dir` should be replaced with `$smarty->setCompileDir()`
+
+Other public properties have been removed altogether, and you should no longer access them:
+
+- `$smarty->_current_file`
+- `$smarty->allow_ambiguous_resources` (ambiguous resources handlers should still work)
+- `$smarty->registered_filters`
+- `$smarty->direct_access_security`
+- `$smarty->trusted_dir`
+- `$smarty->allow_php_templates`
+- `$smarty->php_functions`
+- `$smarty->php_modifiers`
+
+### Backwards incompatible changes to custom plugins
+
+We have dropped support for `$smarty->plugins_dir` and `$smarty->use_include_path`.
+Use `$smarty->addPluginsDir()` or consider writing a proper [extension](api/extending/extensions.md).
+
+The 'insert' plugin type is no longer supported.
+
+The `$cache_attrs` parameter for registered plugins is no longer supported.
+
+### Removed Smarty API methods
+
+Search your code for the following changes:
+
+- `$smarty->getTags()` is no longer supported
+- `$smarty->appendByRef()` should be replaced with `$smarty->append()`
+- `$smarty->assignByRef()` should be replaced with `$smarty->assign()`
+- `$smarty->loadPlugin()` should be replaced with `$smarty->registerPlugin()`
+
+### Removed PHP constants
+
+The following constants have been removed to prevent global side effects.
+
+- `SMARTY_DIR`
+- `SMARTY_SYSPLUGINS_DIR`
+- `SMARTY_PLUGINS_DIR`
+- `SMARTY_MBSTRING`
+- `SMARTY_HELPER_FUNCTIONS_LOADED`
+
+### Other changes
+
+- Smarty now always runs in multibyte mode. Make sure you use the [PHP multibyte extension](https://www.php.net/manual/en/book.mbstring.php) in production for optimal performance.
+- Generated `]*>)|(]*>)|(]*>.*? ]*>)#is',
+ $text,
+ $matches,
+ PREG_OFFSET_CAPTURE | PREG_SET_ORDER
+ )
+ ) {
+ foreach ($matches as $match) {
+ $store[] = $match[0][0];
+ $_length = strlen($match[0][0]);
+ $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
+ $text = substr_replace($text, $replace, $match[0][1] - $_offset, $_length);
+ $_offset += $_length - strlen($replace);
+ $_store++;
+ }
+ }
+ $expressions = [// replace multiple spaces between tags by a single space
+ '#(:SMARTY@!@|>)[\040\011]+(?=@!@SMARTY:|<)#s' => '\1 \2',
+ // remove newline between tags
+ '#(:SMARTY@!@|>)[\040\011]*[\n]\s*(?=@!@SMARTY:|<)#s' => '\1\2',
+ // remove multiple spaces between attributes (but not in attribute values!)
+ '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
+ '#>[\040\011]+$#Ss' => '> ',
+ '#>[\040\011]*[\n]\s*$#Ss' => '>',
+ $this->stripRegEx => '',
+ ];
+ $text = preg_replace(array_keys($expressions), array_values($expressions), $text);
+ $_offset = 0;
+ if (preg_match_all(
+ '#@!@SMARTY:([0-9]+):SMARTY@!@#is',
+ $text,
+ $matches,
+ PREG_OFFSET_CAPTURE | PREG_SET_ORDER
+ )
+ ) {
+ foreach ($matches as $match) {
+ $_length = strlen($match[0][0]);
+ $replace = $store[$match[1][0]];
+ $text = substr_replace($text, $replace, $match[0][1] + $_offset, $_length);
+ $_offset += strlen($replace) - $_length;
+ $_store++;
+ }
+ }
+ return $text;
+ }
+
+ /**
+ * lazy loads internal compile plugin for tag compile objects cached for reuse.
+ *
+ * class name format: \Smarty\Compile\TagName
+ *
+ * @param string $tag tag name
+ *
+ * @return ?\Smarty\Compile\CompilerInterface tag compiler object or null if not found or untrusted by security policy
+ */
+ public function getTagCompiler($tag): ?\Smarty\Compile\CompilerInterface {
+ $tag = strtolower($tag);
+
+ if (isset($this->smarty->security_policy) && !$this->smarty->security_policy->isTrustedTag($tag, $this)) {
+ return null;
+ }
+
+ foreach ($this->smarty->getExtensions() as $extension) {
+ if ($compiler = $extension->getTagCompiler($tag)) {
+ return $compiler;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * lazy loads internal compile plugin for modifier compile objects cached for reuse.
+ *
+ * @param string $modifier tag name
+ *
+ * @return bool|\Smarty\Compile\Modifier\ModifierCompilerInterface tag compiler object or false if not found or untrusted by security policy
+ */
+ public function getModifierCompiler($modifier) {
+
+ if (isset($this->smarty->security_policy) && !$this->smarty->security_policy->isTrustedModifier($modifier, $this)) {
+ return false;
+ }
+
+ foreach ($this->smarty->getExtensions() as $extension) {
+ if ($modifierCompiler = $extension->getModifierCompiler($modifier)) {
+ return $modifierCompiler;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Check for plugins by default plugin handler
+ *
+ * @param string $tag name of tag
+ * @param string $plugin_type type of plugin
+ *
+ * @return callback|null
+ * @throws \Smarty\CompilerException
+ */
+ public function getPluginFromDefaultHandler($tag, $plugin_type) {
+
+ $defaultPluginHandlerFunc = $this->smarty->getDefaultPluginHandlerFunc();
+
+ if (!is_callable($defaultPluginHandlerFunc)) {
+ return null;
+ }
+
+
+ $callback = null;
+ $script = null;
+ $cacheable = true;
+
+ $result = call_user_func_array(
+ $defaultPluginHandlerFunc,
+ [
+ $tag,
+ $plugin_type,
+ null, // This used to pass $this->template, but this parameter has been removed in 5.0
+ &$callback,
+ &$script,
+ &$cacheable,
+ ]
+ );
+ if ($result) {
+ $this->tag_nocache = $this->tag_nocache || !$cacheable;
+ if ($script !== null) {
+ if (is_file($script)) {
+ include_once $script;
+ } else {
+ $this->trigger_template_error("Default plugin handler: Returned script file '{$script}' for '{$tag}' not found");
+ }
+ }
+ if (is_callable($callback)) {
+ return $callback;
+ } else {
+ $this->trigger_template_error("Default plugin handler: Returned callback for '{$tag}' not callable");
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Append code segments and remove unneeded ?> \s?$/D', $left) && preg_match('/^<\?php\s+/', $right)) {
+ $left = preg_replace('/\s*\?>\s?$/D', "\n", $left);
+ $left .= preg_replace('/^<\?php\s+/', '', $right);
+ } else {
+ $left .= $right;
+ }
+ return $left;
+ }
+
+ /**
+ * Inject inline code for nocache template sections
+ * This method gets the content of each template element from the parser.
+ * If the content is compiled code, and it should be not be cached the code is injected
+ * into the rendered output.
+ *
+ * @param string $content content of template element
+ *
+ * @return string content
+ */
+ public function processNocacheCode($content) {
+
+ // If the template is not evaluated, and we have a nocache section and/or a nocache tag
+ // generate replacement code
+ if (!empty($content)
+ && !($this->template->getSource()->handler->recompiled)
+ && $this->caching
+ && $this->isNocacheActive()
+ ) {
+ $this->template->getCompiled()->setNocacheCode(true);
+ $_output = addcslashes($content, '\'\\');
+ $_output =
+ "getNocacheBlockStartMarker() . $_output . $this->getNocacheBlockEndMarker() . "';?>\n";
+ } else {
+ $_output = $content;
+ }
+
+ $this->modifier_plugins = [];
+ $this->suppressNocacheProcessing = false;
+ $this->tag_nocache = false;
+ return $_output;
+ }
+
+
+ private function getNocacheBlockStartMarker(): string {
+ return "/*%%SmartyNocache:{$this->nocache_hash}%%*/";
+ }
+
+ private function getNocacheBlockEndMarker(): string {
+ return "/*/%%SmartyNocache:{$this->nocache_hash}%%*/";
+ }
+
+
+ /**
+ * Get Id
+ *
+ * @param string $input
+ *
+ * @return bool|string
+ */
+ public function getId($input) {
+ if (preg_match('~^([\'"]*)([0-9]*[a-zA-Z_]\w*)\1$~', $input, $match)) {
+ return $match[2];
+ }
+ return false;
+ }
+
+ /**
+ * Set nocache flag in variable or create new variable
+ *
+ * @param string $varName
+ */
+ public function setNocacheInVariable($varName) {
+ // create nocache var to make it know for further compiling
+ if ($_var = $this->getId($varName)) {
+ if ($this->template->hasVariable($_var)) {
+ $this->template->getVariable($_var)->setNocache(true);
+ } else {
+ $this->template->assign($_var, null, true);
+ }
+ }
+ }
+
+ /**
+ * display compiler error messages without dying
+ * If parameter $args is empty it is a parser detected syntax error.
+ * In this case the parser is called to obtain information about expected tokens.
+ * If parameter $args contains a string this is used as error message
+ *
+ * @param string $args individual error message or null
+ * @param string $line line-number
+ * @param null|bool $tagline if true the line number of last tag
+ *
+ * @throws \Smarty\CompilerException when an unexpected token is found
+ */
+ public function trigger_template_error($args = null, $line = null, $tagline = null) {
+ $lex = $this->parser->lex;
+ if ($tagline === true) {
+ // get line number of Tag
+ $line = $lex->taglineno;
+ } elseif (!isset($line)) {
+ // get template source line which has error
+ $line = $lex->line;
+ } else {
+ $line = (int)$line;
+ }
+ if (in_array(
+ $this->template->getSource()->type,
+ [
+ 'eval',
+ 'string',
+ ]
+ )
+ ) {
+ $templateName = $this->template->getSource()->type . ':' . trim(
+ preg_replace(
+ '![\t\r\n]+!',
+ ' ',
+ strlen($lex->data) > 40 ?
+ substr($lex->data, 0, 40) .
+ '...' : $lex->data
+ )
+ );
+ } else {
+ $templateName = $this->template->getSource()->getFullResourceName();
+ }
+ // $line += $this->trace_line_offset;
+ $match = preg_split("/\n/", $lex->data);
+ $error_text =
+ 'Syntax error in template "' . (empty($this->trace_filepath) ? $templateName : $this->trace_filepath) .
+ '" on line ' . ($line + $this->trace_line_offset) . ' "' .
+ trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])) . '" ';
+ if (isset($args)) {
+ // individual error message
+ $error_text .= $args;
+ } else {
+ $expect = [];
+ // expected token from parser
+ $error_text .= ' - Unexpected "' . $lex->value . '"';
+ if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4) {
+ foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) {
+ $exp_token = $this->parser->yyTokenName[$token];
+ if (isset($lex->smarty_token_names[$exp_token])) {
+ // token type from lexer
+ $expect[] = '"' . $lex->smarty_token_names[$exp_token] . '"';
+ } else {
+ // otherwise internal token name
+ $expect[] = $this->parser->yyTokenName[$token];
+ }
+ }
+ $error_text .= ', expected one of: ' . implode(' , ', $expect);
+ }
+ }
+ if ($this->smarty->_parserdebug) {
+ $this->parser->errorRunDown();
+ echo ob_get_clean();
+ flush();
+ }
+ $e = new CompilerException(
+ $error_text,
+ 0,
+ $this->template->getSource()->getFilepath() ?? $this->template->getSource()->getFullResourceName(),
+ $line
+ );
+ $e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1]));
+ $e->desc = $args;
+ $e->template = $this->template->getSource()->getFullResourceName();
+ throw $e;
+ }
+
+ /**
+ * Return var_export() value with all white spaces removed
+ *
+ * @param mixed $value
+ *
+ * @return string
+ */
+ public function getVarExport($value) {
+ return preg_replace('/\s/', '', var_export($value, true));
+ }
+
+ /**
+ * enter double quoted string
+ * - save tag stack count
+ */
+ public function enterDoubleQuote() {
+ array_push($this->_tag_stack_count, $this->getTagStackCount());
+ }
+
+ /**
+ * Return tag stack count
+ *
+ * @return int
+ */
+ public function getTagStackCount() {
+ return count($this->_tag_stack);
+ }
+
+ /**
+ * @param $lexerPreg
+ *
+ * @return mixed
+ */
+ public function replaceDelimiter($lexerPreg) {
+ return str_replace(
+ ['SMARTYldel', 'SMARTYliteral', 'SMARTYrdel', 'SMARTYautoliteral', 'SMARTYal'],
+ [
+ $this->ldelPreg, $this->literalPreg, $this->rdelPreg,
+ $this->smarty->getAutoLiteral() ? '{1,}' : '{9}',
+ $this->smarty->getAutoLiteral() ? '' : '\\s*',
+ ],
+ $lexerPreg
+ );
+ }
+
+ /**
+ * Build lexer regular expressions for left and right delimiter and user defined literals
+ */
+ public function initDelimiterPreg() {
+ $ldel = $this->smarty->getLeftDelimiter();
+ $this->ldelLength = strlen($ldel);
+ $this->ldelPreg = '';
+ foreach (str_split($ldel, 1) as $chr) {
+ $this->ldelPreg .= '[' . preg_quote($chr, '/') . ']';
+ }
+ $rdel = $this->smarty->getRightDelimiter();
+ $this->rdelLength = strlen($rdel);
+ $this->rdelPreg = '';
+ foreach (str_split($rdel, 1) as $chr) {
+ $this->rdelPreg .= '[' . preg_quote($chr, '/') . ']';
+ }
+ $literals = $this->smarty->getLiterals();
+ if (!empty($literals)) {
+ foreach ($literals as $key => $literal) {
+ $literalPreg = '';
+ foreach (str_split($literal, 1) as $chr) {
+ $literalPreg .= '[' . preg_quote($chr, '/') . ']';
+ }
+ $literals[$key] = $literalPreg;
+ }
+ $this->literalPreg = '|' . implode('|', $literals);
+ } else {
+ $this->literalPreg = '';
+ }
+ }
+
+ /**
+ * leave double quoted string
+ * - throw exception if block in string was not closed
+ *
+ * @throws \Smarty\CompilerException
+ */
+ public function leaveDoubleQuote() {
+ if (array_pop($this->_tag_stack_count) !== $this->getTagStackCount()) {
+ $tag = $this->getOpenBlockTag();
+ $this->trigger_template_error(
+ "unclosed '{{$tag}}' in doubled quoted string",
+ null,
+ true
+ );
+ }
+ }
+
+ /**
+ * Get left delimiter preg
+ *
+ * @return string
+ */
+ public function getLdelPreg() {
+ return $this->ldelPreg;
+ }
+
+ /**
+ * Get right delimiter preg
+ *
+ * @return string
+ */
+ public function getRdelPreg() {
+ return $this->rdelPreg;
+ }
+
+ /**
+ * Get length of left delimiter
+ *
+ * @return int
+ */
+ public function getLdelLength() {
+ return $this->ldelLength;
+ }
+
+ /**
+ * Get length of right delimiter
+ *
+ * @return int
+ */
+ public function getRdelLength() {
+ return $this->rdelLength;
+ }
+
+ /**
+ * Get name of current open block tag
+ *
+ * @return string|boolean
+ */
+ public function getOpenBlockTag() {
+ $tagCount = $this->getTagStackCount();
+ if ($tagCount) {
+ return $this->_tag_stack[$tagCount - 1][0];
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Check if $value contains variable elements
+ *
+ * @param mixed $value
+ *
+ * @return bool|int
+ */
+ public function isVariable($value) {
+ if (is_string($value)) {
+ return preg_match('/[$(]/', $value);
+ }
+ if (is_bool($value) || is_numeric($value)) {
+ return false;
+ }
+ if (is_array($value)) {
+ foreach ($value as $k => $v) {
+ if ($this->isVariable($k) || $this->isVariable($v)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return false;
+ }
+
+ /**
+ * Get new prefix variable name
+ *
+ * @return string
+ */
+ public function getNewPrefixVariable() {
+ ++self::$prefixVariableNumber;
+ return $this->getPrefixVariable();
+ }
+
+ /**
+ * Get current prefix variable name
+ *
+ * @return string
+ */
+ public function getPrefixVariable() {
+ return '$_prefixVariable' . self::$prefixVariableNumber;
+ }
+
+ /**
+ * append code to prefix buffer
+ *
+ * @param string $code
+ */
+ public function appendPrefixCode($code) {
+ $this->prefix_code[] = $code;
+ }
+
+ /**
+ * get prefix code string
+ *
+ * @return string
+ */
+ public function getPrefixCode() {
+ $code = '';
+ $prefixArray = array_merge($this->prefix_code, array_pop($this->prefixCodeStack));
+ $this->prefixCodeStack[] = [];
+ foreach ($prefixArray as $c) {
+ $code = $this->appendCode($code, (string) $c);
+ }
+ $this->prefix_code = [];
+ return $code;
+ }
+
+ public function cStyleComment($string) {
+ return '/*' . str_replace('*/', '* /', $string) . '*/';
+ }
+
+ public function compileChildBlock() {
+ return $this->blockCompiler->compileChild($this);
+ }
+
+ public function compileParentBlock() {
+ return $this->blockCompiler->compileParent($this);
+ }
+
+ /**
+ * Compile Tag
+ *
+ * @param string $tag tag name
+ * @param array $args array with tag attributes
+ * @param array $parameter array with compilation parameter
+ *
+ * @return string compiled code
+ * @throws Exception
+ * @throws CompilerException
+ */
+ private function compileTag2($tag, $args, $parameter) {
+ // $args contains the attributes parsed and compiled by the lexer/parser
+
+ $this->handleNocacheFlag($args);
+
+ // compile built-in tags
+ if ($tagCompiler = $this->getTagCompiler($tag)) {
+ if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
+ $this->tag_nocache = $this->tag_nocache | !$tagCompiler->isCacheable();
+ $_output = $tagCompiler->compile($args, $this, $parameter);
+ if (!empty($parameter['modifierlist'])) {
+ throw new CompilerException('No modifiers allowed on ' . $tag);
+ }
+ return $_output;
+ }
+ }
+
+ // call to function previously defined by {function} tag
+ if ($this->canCompileTemplateFunctionCall($tag)) {
+
+ if (!empty($parameter['modifierlist'])) {
+ throw new CompilerException('No modifiers allowed on ' . $tag);
+ }
+
+ $args['_attr']['name'] = "'{$tag}'";
+ $tagCompiler = $this->getTagCompiler('call');
+ return $tagCompiler === null ? false : $tagCompiler->compile($args, $this, $parameter);
+ }
+
+ // remaining tastes: (object-)function, (object-function-)block, custom-compiler
+ // opening and closing tags for these are handled with the same handler
+ $base_tag = $this->getBaseTag($tag);
+
+ // check if tag is a registered object
+ if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter['object_method'])) {
+ return $this->compileRegisteredObjectMethodCall($base_tag, $args, $parameter, $tag);
+ }
+
+ // check if tag is a function
+ if ($this->smarty->getFunctionHandler($base_tag)) {
+ if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
+ return (new \Smarty\Compile\PrintExpressionCompiler())->compile(
+ ['nofilter'], // functions are never auto-escaped
+ $this,
+ ['value' => $this->compileFunctionCall($base_tag, $args, $parameter)]
+ );
+ }
+ }
+
+ // check if tag is a block
+ if ($this->smarty->getBlockHandler($base_tag)) {
+ if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
+ return $this->blockCompiler->compile($args, $this, $parameter, $tag, $base_tag);
+ }
+ }
+
+ // the default plugin handler is a handler of last resort, it may also handle not specifically registered tags.
+ if ($callback = $this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_COMPILER)) {
+ if (!empty($parameter['modifierlist'])) {
+ throw new CompilerException('No modifiers allowed on ' . $base_tag);
+ }
+ $tagCompiler = new \Smarty\Compile\Tag\BCPluginWrapper($callback);
+ return $tagCompiler->compile($args, $this, $parameter);
+ }
+
+ if ($this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_FUNCTION)) {
+ return $this->defaultHandlerFunctionCallCompiler->compile($args, $this, $parameter, $tag, $base_tag);
+ }
+
+ if ($this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_BLOCK)) {
+ return $this->defaultHandlerBlockCompiler->compile($args, $this, $parameter, $tag, $base_tag);
+ }
+
+ $this->trigger_template_error("unknown tag '{$tag}'", null, true);
+ }
+
+ /**
+ * Sets $this->tag_nocache if attributes contain the 'nocache' flag.
+ *
+ * @param array $attributes
+ *
+ * @return void
+ */
+ private function handleNocacheFlag(array $attributes) {
+ foreach ($attributes as $value) {
+ if (is_string($value) && trim($value, '\'" ') == 'nocache') {
+ $this->tag_nocache = true;
+ }
+ }
+ }
+
+ private function getBaseTag($tag) {
+ if (strlen($tag) < 6 || substr($tag, -5) !== 'close') {
+ return $tag;
+ } else {
+ return substr($tag, 0, -5);
+ }
+ }
+
+ /**
+ * Compiles the output of a variable or expression.
+ *
+ * @param $value
+ * @param $attributes
+ * @param $modifiers
+ *
+ * @return string
+ * @throws Exception
+ */
+ public function compilePrintExpression($value, $attributes = [], $modifiers = null) {
+ $this->handleNocacheFlag($attributes);
+ return $this->printExpressionCompiler->compile($attributes, $this, [
+ 'value'=> $value,
+ 'modifierlist' => $modifiers,
+ ]);
+ }
+
+ /**
+ * method to compile a Smarty template
+ *
+ * @param mixed $_content template source
+ * @param bool $isTemplateSource
+ *
+ * @return bool true if compiling succeeded, false if it failed
+ * @throws \Smarty\CompilerException
+ */
+ protected function doCompile($_content, $isTemplateSource = false) {
+ /* here is where the compiling takes place. Smarty
+ tags in the templates are replaces with PHP code,
+ then written to compiled files. */
+ // init the lexer/parser to compile the template
+ $this->parser = new TemplateParser(
+ new TemplateLexer(
+ str_replace(
+ [
+ "\r\n",
+ "\r",
+ ],
+ "\n",
+ $_content
+ ),
+ $this
+ ),
+ $this
+ );
+ if ($isTemplateSource && $this->template->caching) {
+ $this->parser->insertPhpCode("getCompiled()->nocache_hash = '{$this->nocache_hash}';\n?>\n");
+ }
+ if ($this->smarty->_parserdebug) {
+ $this->parser->PrintTrace();
+ $this->parser->lex->PrintTrace();
+ }
+ // get tokens from lexer and parse them
+ while ($this->parser->lex->yylex()) {
+ if ($this->smarty->_parserdebug) {
+ echo "Line {$this->parser->lex->line} Parsing {$this->parser->yyTokenName[$this->parser->lex->token]} Token " .
+ $this->parser->lex->value;
+ }
+ $this->parser->doParse($this->parser->lex->token, $this->parser->lex->value);
+ }
+ // finish parsing process
+ $this->parser->doParse(0, 0);
+ // check for unclosed tags
+ if ($this->getTagStackCount() > 0) {
+ // get stacked info
+ [$openTag, $_data] = array_pop($this->_tag_stack);
+ $this->trigger_template_error(
+ "unclosed " . $this->smarty->getLeftDelimiter() . $openTag .
+ $this->smarty->getRightDelimiter() . " tag"
+ );
+ }
+ // call post compile callbacks
+ foreach ($this->postCompileCallbacks as $cb) {
+ $parameter = $cb;
+ $parameter[0] = $this;
+ call_user_func_array($cb[0], $parameter);
+ }
+ // return compiled code
+ return $this->prefixCompiledCode . $this->parser->retvalue . $this->postfixCompiledCode;
+ }
+
+ /**
+ * Register a post compile callback
+ * - when the callback is called after template compiling the compiler object will be inserted as first parameter
+ *
+ * @param callback $callback
+ * @param array $parameter optional parameter array
+ * @param string $key optional key for callback
+ * @param bool $replace if true replace existing keyed callback
+ */
+ public function registerPostCompileCallback($callback, $parameter = [], $key = null, $replace = false) {
+ array_unshift($parameter, $callback);
+ if (isset($key)) {
+ if ($replace || !isset($this->postCompileCallbacks[$key])) {
+ $this->postCompileCallbacks[$key] = $parameter;
+ }
+ } else {
+ $this->postCompileCallbacks[] = $parameter;
+ }
+ }
+
+ /**
+ * Remove a post compile callback
+ *
+ * @param string $key callback key
+ */
+ public function unregisterPostCompileCallback($key) {
+ unset($this->postCompileCallbacks[$key]);
+ }
+
+ /**
+ * @param string $tag
+ *
+ * @return bool
+ * @throws Exception
+ */
+ private function canCompileTemplateFunctionCall(string $tag): bool {
+ return
+ isset($this->parent_compiler->tpl_function[$tag])
+ || (
+ $this->template->getSmarty()->hasRuntime('TplFunction')
+ && ($this->template->getSmarty()->getRuntime('TplFunction')->getTplFunction($this->template, $tag) !== false)
+ );
+ }
+
+ /**
+ * @throws CompilerException
+ */
+ private function compileRegisteredObjectMethodCall(string $base_tag, array $args, array $parameter, string $tag) {
+
+ $method = $parameter['object_method'];
+ $allowedAsBlockFunction = in_array($method, $this->smarty->registered_objects[$base_tag][3]);
+
+ if ($base_tag === $tag) {
+ // opening tag
+
+ $allowedAsNormalFunction = empty($this->smarty->registered_objects[$base_tag][1])
+ || in_array($method, $this->smarty->registered_objects[$base_tag][1]);
+
+ if ($allowedAsBlockFunction) {
+ return $this->objectMethodBlockCompiler->compile($args, $this, $parameter, $tag, $method);
+ } elseif ($allowedAsNormalFunction) {
+ return $this->objectMethodCallCompiler->compile($args, $this, $parameter, $tag, $method);
+ }
+
+ $this->trigger_template_error(
+ 'not allowed method "' . $method . '" in registered object "' .
+ $tag . '"',
+ null,
+ true
+ );
+ }
+
+ // closing tag
+ if ($allowedAsBlockFunction) {
+ return $this->objectMethodBlockCompiler->compile($args, $this, $parameter, $tag, $method);
+ }
+
+ $this->trigger_template_error(
+ 'not allowed closing tag method "' . $method .
+ '" in registered object "' . $base_tag . '"',
+ null,
+ true
+ );
+ }
+
+ public function compileFunctionCall(string $base_tag, array $args, array $parameter = []) {
+ return $this->functionCallCompiler->compile($args, $this, $parameter, $base_tag, $base_tag);
+ }
+
+ public function compileModifierInExpression(string $function, array $_attr) {
+ $value = array_shift($_attr);
+ return $this->compileModifier([array_merge([$function], $_attr)], $value);
+ }
+
+ /**
+ * @return TemplateParser|null
+ */
+ public function getParser(): ?TemplateParser {
+ return $this->parser;
+ }
+
+ /**
+ * @param TemplateParser|null $parser
+ */
+ public function setParser(?TemplateParser $parser): void {
+ $this->parser = $parser;
+ }
+
+ /**
+ * @return \Smarty\Template|null
+ */
+ public function getTemplate(): ?\Smarty\Template {
+ return $this->template;
+ }
+
+ /**
+ * @param \Smarty\Template|null $template
+ */
+ public function setTemplate(?\Smarty\Template $template): void {
+ $this->template = $template;
+ }
+
+ /**
+ * @return Template|null
+ */
+ public function getParentCompiler(): ?Template {
+ return $this->parent_compiler;
+ }
+
+ /**
+ * @param Template|null $parent_compiler
+ */
+ public function setParentCompiler(?Template $parent_compiler): void {
+ $this->parent_compiler = $parent_compiler;
+ }
+
+
+ /**
+ * Push opening tag name on stack
+ * Optionally additional data can be saved on stack
+ *
+ * @param string $openTag the opening tag's name
+ * @param mixed $data optional data saved
+ */
+ public function openTag($openTag, $data = null) {
+ $this->_tag_stack[] = [$openTag, $data];
+ if ($openTag == 'nocache') {
+ $this->noCacheStackDepth++;
+ }
+ }
+
+ /**
+ * Pop closing tag
+ * Raise an error if this stack-top doesn't match with expected opening tags
+ *
+ * @param array|string $expectedTag the expected opening tag names
+ *
+ * @return mixed any type the opening tag's name or saved data
+ * @throws CompilerException
+ */
+ public function closeTag($expectedTag) {
+ if ($this->getTagStackCount() > 0) {
+ // get stacked info
+ [$_openTag, $_data] = array_pop($this->_tag_stack);
+ // open tag must match with the expected ones
+ if (in_array($_openTag, (array)$expectedTag)) {
+
+ if ($_openTag == 'nocache') {
+ $this->noCacheStackDepth--;
+ }
+
+ if (is_null($_data)) {
+ // return opening tag
+ return $_openTag;
+ } else {
+ // return restored data
+ return $_data;
+ }
+ }
+ // wrong nesting of tags
+ $this->trigger_template_error("unclosed '" . $this->getTemplate()->getLeftDelimiter() . "{$_openTag}" .
+ $this->getTemplate()->getRightDelimiter() . "' tag");
+ return;
+ }
+ // wrong nesting of tags
+ $this->trigger_template_error('unexpected closing tag', null, true);
+ }
+
+ /**
+ * Returns true if we are in a {nocache}...{/nocache} block, but false if inside {block} tag inside a {nocache} block...
+ * @return bool
+ */
+ public function isNocacheActive(): bool {
+ return !$this->suppressNocacheProcessing && ($this->noCacheStackDepth > 0 || $this->tag_nocache);
+ }
+
+ /**
+ * Returns the full tag stack, used in the compiler for {break}
+ * @return array
+ */
+ public function getTagStack(): array {
+ return $this->_tag_stack;
+ }
+
+ /**
+ * Should the next variable output be raw (true) or auto-escaped (false)
+ * @return bool
+ */
+ public function isRawOutput(): bool {
+ return $this->raw_output;
+ }
+
+ /**
+ * Should the next variable output be raw (true) or auto-escaped (false)
+ * @param bool $raw_output
+ * @return void
+ */
+ public function setRawOutput(bool $raw_output): void {
+ $this->raw_output = $raw_output;
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/CompilerException.php b/src/includes/smarty-5.4.1/src/CompilerException.php
new file mode 100644
index 0000000..e3d67b4
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/CompilerException.php
@@ -0,0 +1,73 @@
+file = $filename;
+ }
+ if ($line) {
+ $this->line = $line;
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString() {
+ return ' --> Smarty Compiler: ' . $this->message . ' <-- ';
+ }
+
+ /**
+ * @param int $line
+ */
+ public function setLine($line) {
+ $this->line = $line;
+ }
+
+ /**
+ * The template source snippet relating to the error
+ *
+ * @type string|null
+ */
+ public $source = null;
+
+ /**
+ * The raw text of the error message
+ *
+ * @type string|null
+ */
+ public $desc = null;
+
+ /**
+ * The resource identifier or template name
+ *
+ * @type string|null
+ */
+ public $template = null;
+}
diff --git a/src/includes/smarty-5.4.1/src/Data.php b/src/includes/smarty-5.4.1/src/Data.php
new file mode 100644
index 0000000..6ae823d
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Data.php
@@ -0,0 +1,521 @@
+smarty = $smarty;
+ if (is_object($_parent)) {
+ // when object set up back pointer
+ $this->parent = $_parent;
+ } elseif (is_array($_parent)) {
+ // set up variable values
+ foreach ($_parent as $_key => $_val) {
+ $this->assign($_key, $_val);
+ }
+ } elseif ($_parent !== null) {
+ throw new Exception('Wrong type for template variables');
+ }
+ }
+
+ /**
+ * assigns a Smarty variable
+ *
+ * @param array|string $tpl_var the template variable name(s)
+ * @param mixed $value the value to assign
+ * @param boolean $nocache if true any output of this variable will be not cached
+ * @param int $scope one of self::SCOPE_* constants
+ *
+ * @return Data current Data (or Smarty or \Smarty\Template) instance for
+ * chaining
+ */
+ public function assign($tpl_var, $value = null, $nocache = false, $scope = null)
+ {
+ if (is_array($tpl_var)) {
+ foreach ($tpl_var as $_key => $_val) {
+ $this->assign($_key, $_val, $nocache, $scope);
+ }
+ return $this;
+ }
+ switch ($scope ?? $this->getDefaultScope()) {
+ case self::SCOPE_GLOBAL:
+ case self::SCOPE_SMARTY:
+ $this->getSmarty()->assign($tpl_var, $value);
+ break;
+ case self::SCOPE_TPL_ROOT:
+ $ptr = $this;
+ while (isset($ptr->parent) && ($ptr->parent instanceof Template)) {
+ $ptr = $ptr->parent;
+ }
+ $ptr->assign($tpl_var, $value);
+ break;
+ case self::SCOPE_ROOT:
+ $ptr = $this;
+ while (isset($ptr->parent) && !($ptr->parent instanceof Smarty)) {
+ $ptr = $ptr->parent;
+ }
+ $ptr->assign($tpl_var, $value);
+ break;
+ case self::SCOPE_PARENT:
+ if ($this->parent) {
+ $this->parent->assign($tpl_var, $value);
+ } else {
+ // assign local as fallback
+ $this->assign($tpl_var, $value);
+ }
+ break;
+ case self::SCOPE_LOCAL:
+ default:
+ if (isset($this->tpl_vars[$tpl_var])) {
+ $this->tpl_vars[$tpl_var]->setValue($value);
+ if ($nocache) {
+ $this->tpl_vars[$tpl_var]->setNocache(true);
+ }
+ } else {
+ $this->tpl_vars[$tpl_var] = new Variable($value, $nocache);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * appends values to template variables
+ *
+ * @param array|string $tpl_var the template variable name(s)
+ * @param mixed $value the value to append
+ * @param bool $merge flag if array elements shall be merged
+ * @param bool $nocache if true any output of this variable will
+ * be not cached
+ *
+ * @return Data
+ * @api Smarty::append()
+ */
+ public function append($tpl_var, $value = null, $merge = false, $nocache = false)
+ {
+ if (is_array($tpl_var)) {
+ foreach ($tpl_var as $_key => $_val) {
+ $this->append($_key, $_val, $merge, $nocache);
+ }
+ } else {
+
+ $newValue = $this->getValue($tpl_var) ?? [];
+ if (!is_array($newValue)) {
+ $newValue = (array) $newValue;
+ }
+
+ if ($merge && is_array($value)) {
+ foreach ($value as $_mkey => $_mval) {
+ $newValue[$_mkey] = $_mval;
+ }
+ } else {
+ $newValue[] = $value;
+ }
+
+ $this->assign($tpl_var, $newValue, $nocache);
+ }
+ return $this;
+ }
+
+ /**
+ * assigns a global Smarty variable
+ *
+ * @param string $varName the global variable name
+ * @param mixed $value the value to assign
+ * @param boolean $nocache if true any output of this variable will be not cached
+ *
+ * @return Data
+ * @deprecated since 5.0
+ */
+ public function assignGlobal($varName, $value = null, $nocache = false)
+ {
+ trigger_error(__METHOD__ . " is deprecated. Use \\Smarty\\Smarty::assign() to assign a variable " .
+ " at the Smarty level.", E_USER_DEPRECATED);
+ return $this->getSmarty()->assign($varName, $value, $nocache);
+ }
+
+ /**
+ * Returns a single or all template variables
+ *
+ * @param string $varName variable name or null
+ * @param bool $searchParents include parent templates?
+ *
+ * @return mixed variable value or or array of variables
+ * @api Smarty::getTemplateVars()
+ *
+ */
+ public function getTemplateVars($varName = null, $searchParents = true)
+ {
+ if (isset($varName)) {
+ return $this->getValue($varName, $searchParents);
+ }
+
+ return array_merge(
+ $this->parent && $searchParents ? $this->parent->getTemplateVars() : [],
+ array_map(function(Variable $var) { return $var->getValue(); }, $this->tpl_vars)
+ );
+ }
+
+ /**
+ * Wrapper for ::getVariable()
+ *
+ * @deprecated since 5.0
+ *
+ * @param $varName
+ * @param $searchParents
+ * @param $errorEnable
+ *
+ * @return void
+ */
+ public function _getVariable($varName, $searchParents = true, $errorEnable = true) {
+ trigger_error('Using ::_getVariable() to is deprecated and will be ' .
+ 'removed in a future release. Use getVariable() instead.', E_USER_DEPRECATED);
+ return $this->getVariable($varName, $searchParents, $errorEnable);
+ }
+
+ /**
+ * Gets the object of a Smarty variable
+ *
+ * @param string $varName the name of the Smarty variable
+ * @param bool $searchParents search also in parent data
+ * @param bool $errorEnable
+ *
+ * @return Variable
+ */
+ public function getVariable($varName, $searchParents = true, $errorEnable = true) {
+ if (isset($this->tpl_vars[$varName])) {
+ return $this->tpl_vars[$varName];
+ }
+
+ if ($searchParents && $this->parent) {
+ return $this->parent->getVariable($varName, $searchParents, $errorEnable);
+ }
+
+ if ($errorEnable && $this->getSmarty()->error_unassigned) {
+ // force a notice
+ $x = $$varName;
+ }
+ return new UndefinedVariable();
+ }
+
+ /**
+ * Directly sets a complete Variable object in the variable with the given name.
+ * @param $varName
+ * @param Variable $variableObject
+ *
+ * @return void
+ */
+ public function setVariable($varName, Variable $variableObject) {
+ $this->tpl_vars[$varName] = $variableObject;
+ }
+
+ /**
+ * Indicates if given variable has been set.
+ * @param $varName
+ *
+ * @return bool
+ */
+ public function hasVariable($varName): bool {
+ return !($this->getVariable($varName, true, false) instanceof UndefinedVariable);
+ }
+
+ /**
+ * Returns the value of the Smarty\Variable given by $varName, or null if the variable does not exist.
+ *
+ * @param $varName
+ * @param bool $searchParents
+ *
+ * @return mixed|null
+ */
+ public function getValue($varName, $searchParents = true) {
+ $variable = $this->getVariable($varName, $searchParents);
+ return isset($variable) ? $variable->getValue() : null;
+ }
+
+ /**
+ * load config variables into template object
+ *
+ * @param array $new_config_vars
+ */
+ public function assignConfigVars($new_config_vars, array $sections = []) {
+
+ // copy global config vars
+ foreach ($new_config_vars['vars'] as $variable => $value) {
+ if ($this->getSmarty()->config_overwrite || !isset($this->config_vars[$variable])) {
+ $this->config_vars[$variable] = $value;
+ } else {
+ $this->config_vars[$variable] = array_merge((array)$this->config_vars[$variable], (array)$value);
+ }
+ }
+
+ foreach ($sections as $tpl_section) {
+ if (isset($new_config_vars['sections'][$tpl_section])) {
+ foreach ($new_config_vars['sections'][$tpl_section]['vars'] as $variable => $value) {
+ if ($this->getSmarty()->config_overwrite || !isset($this->config_vars[$variable])) {
+ $this->config_vars[$variable] = $value;
+ } else {
+ $this->config_vars[$variable] = array_merge((array)$this->config_vars[$variable], (array)$value);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get Smarty object
+ *
+ * @return Smarty
+ */
+ public function getSmarty()
+ {
+ return $this->smarty;
+ }
+
+ /**
+ * clear the given assigned template variable(s).
+ *
+ * @param string|array $tpl_var the template variable(s) to clear
+ *
+ * @return Data
+ *
+ * @api Smarty::clearAssign()
+ */
+ public function clearAssign($tpl_var)
+ {
+ if (is_array($tpl_var)) {
+ foreach ($tpl_var as $curr_var) {
+ unset($this->tpl_vars[ $curr_var ]);
+ }
+ } else {
+ unset($this->tpl_vars[ $tpl_var ]);
+ }
+ return $this;
+ }
+
+ /**
+ * clear all the assigned template variables.
+ *
+ * @return Data
+ *
+ * @api Smarty::clearAllAssign()
+ */
+ public function clearAllAssign()
+ {
+ $this->tpl_vars = array();
+ return $this;
+ }
+
+ /**
+ * clear a single or all config variables
+ *
+ * @param string|null $name variable name or null
+ *
+ * @return Data
+ *
+ * @api Smarty::clearConfig()
+ */
+ public function clearConfig($name = null)
+ {
+ if (isset($name)) {
+ unset($this->config_vars[ $name ]);
+ } else {
+ $this->config_vars = array();
+ }
+ return $this;
+ }
+
+ /**
+ * Gets a config variable value
+ *
+ * @param string $varName the name of the config variable
+ *
+ * @return mixed the value of the config variable
+ * @throws Exception
+ */
+ public function getConfigVariable($varName)
+ {
+
+ if (isset($this->config_vars[$varName])) {
+ return $this->config_vars[$varName];
+ }
+
+ $returnValue = $this->parent ? $this->parent->getConfigVariable($varName) : null;
+
+ if ($returnValue === null && $this->getSmarty()->error_unassigned) {
+ throw new Exception("Undefined variable $varName");
+ }
+
+ return $returnValue;
+ }
+
+ public function hasConfigVariable($varName): bool {
+ try {
+ return $this->getConfigVariable($varName) !== null;
+ } catch (Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a single or all config variables
+ *
+ * @param string $varname variable name or null
+ *
+ * @return mixed variable value or or array of variables
+ * @throws Exception
+ *
+ * @api Smarty::getConfigVars()
+ */
+ public function getConfigVars($varname = null)
+ {
+ if (isset($varname)) {
+ return $this->getConfigVariable($varname);
+ }
+
+ return array_merge($this->parent ? $this->parent->getConfigVars() : [], $this->config_vars);
+ }
+
+ /**
+ * load a config file, optionally load just selected sections
+ *
+ * @param string $config_file filename
+ * @param mixed $sections array of section names, single
+ * section or null
+
+ * @returns $this
+ * @throws \Exception
+ *
+ * @api Smarty::configLoad()
+ */
+ public function configLoad($config_file, $sections = null)
+ {
+ $template = $this->getSmarty()->doCreateTemplate($config_file, null, null, $this, null, null, true);
+ $template->caching = Smarty::CACHING_OFF;
+ $template->assign('sections', (array) $sections ?? []);
+ // trigger a call to $this->assignConfigVars
+ $template->fetch();
+ return $this;
+ }
+
+ /**
+ * Sets the default scope for new variables assigned in this template.
+ * @param int $scope
+ *
+ * @return void
+ */
+ protected function setDefaultScope(int $scope) {
+ $this->defaultScope = $scope;
+ }
+
+ /**
+ * Returns the default scope for new variables assigned in this template.
+ * @return int
+ */
+ public function getDefaultScope(): int {
+ return $this->defaultScope;
+ }
+
+ /**
+ * @return Data|Smarty|null
+ */
+ public function getParent() {
+ return $this->parent;
+ }
+
+ /**
+ * @param Data|Smarty|null $parent
+ */
+ public function setParent($parent): void {
+ $this->parent = $parent;
+ }
+
+ public function pushStack(): void {
+ $stackList = [];
+ foreach ($this->tpl_vars as $name => $variable) {
+ $stackList[$name] = clone $variable; // variables are stored in Variable objects
+ }
+ $this->_var_stack[] = $this->tpl_vars;
+ $this->tpl_vars = $stackList;
+
+ $this->_config_stack[] = $this->config_vars;
+ }
+
+ public function popStack(): void {
+ $this->tpl_vars = array_pop($this->_var_stack);
+ $this->config_vars = array_pop($this->_config_stack);
+ }
+}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_debug.php b/src/includes/smarty-5.4.1/src/Debug.php
similarity index 53%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_debug.php
rename to src/includes/smarty-5.4.1/src/Debug.php
index 24b233e..ab1a887 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_debug.php
+++ b/src/includes/smarty-5.4.1/src/Debug.php
@@ -1,34 +1,28 @@
_isSubTpl()) {
$this->index++;
@@ -64,39 +58,30 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* End logging of cache time
*
- * @param \Smarty_Internal_Template $template cached template
+ * @param Template $template cached template
*/
- public function end_template(Smarty_Internal_Template $template)
+ public function end_template(Template $template)
{
$key = $this->get_key($template);
$this->template_data[ $this->index ][ $key ][ 'total_time' ] +=
microtime(true) - $this->template_data[ $this->index ][ $key ][ 'start_template_time' ];
- //$this->template_data[$this->index][$key]['properties'] = $template->properties;
}
/**
* Start logging of compile time
*
- * @param \Smarty_Internal_Template $template
+ * @param Template $template
*/
- public function start_compile(Smarty_Internal_Template $template)
+ public function start_compile(Template $template)
{
static $_is_stringy = array('string' => true, 'eval' => true);
- if (!empty($template->compiler->trace_uid)) {
- $key = $template->compiler->trace_uid;
+ if (!empty($template->getCompiler()->trace_uid)) {
+ $key = $template->getCompiler()->trace_uid;
if (!isset($this->template_data[ $this->index ][ $key ])) {
- if (isset($_is_stringy[ $template->source->type ])) {
- $this->template_data[ $this->index ][ $key ][ 'name' ] =
- '\'' . substr($template->source->name, 0, 25) . '...\'';
- } else {
- $this->template_data[ $this->index ][ $key ][ 'name' ] = $template->source->filepath;
- }
- $this->template_data[ $this->index ][ $key ][ 'compile_time' ] = 0;
- $this->template_data[ $this->index ][ $key ][ 'render_time' ] = 0;
- $this->template_data[ $this->index ][ $key ][ 'cache_time' ] = 0;
+ $this->saveTemplateData($_is_stringy, $template, $key);
}
} else {
- if (isset($this->ignore_uid[ $template->source->uid ])) {
+ if (isset($this->ignore_uid[ $template->getSource()->uid ])) {
return;
}
$key = $this->get_key($template);
@@ -107,14 +92,14 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* End logging of compile time
*
- * @param \Smarty_Internal_Template $template
+ * @param Template $template
*/
- public function end_compile(Smarty_Internal_Template $template)
+ public function end_compile(Template $template)
{
- if (!empty($template->compiler->trace_uid)) {
- $key = $template->compiler->trace_uid;
+ if (!empty($template->getCompiler()->trace_uid)) {
+ $key = $template->getCompiler()->trace_uid;
} else {
- if (isset($this->ignore_uid[ $template->source->uid ])) {
+ if (isset($this->ignore_uid[ $template->getSource()->uid ])) {
return;
}
$key = $this->get_key($template);
@@ -126,9 +111,9 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* Start logging of render time
*
- * @param \Smarty_Internal_Template $template
+ * @param Template $template
*/
- public function start_render(Smarty_Internal_Template $template)
+ public function start_render(Template $template)
{
$key = $this->get_key($template);
$this->template_data[ $this->index ][ $key ][ 'start_time' ] = microtime(true);
@@ -137,9 +122,9 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* End logging of compile time
*
- * @param \Smarty_Internal_Template $template
+ * @param Template $template
*/
- public function end_render(Smarty_Internal_Template $template)
+ public function end_render(Template $template)
{
$key = $this->get_key($template);
$this->template_data[ $this->index ][ $key ][ 'render_time' ] +=
@@ -149,9 +134,9 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* Start logging of cache time
*
- * @param \Smarty_Internal_Template $template cached template
+ * @param Template $template cached template
*/
- public function start_cache(Smarty_Internal_Template $template)
+ public function start_cache(Template $template)
{
$key = $this->get_key($template);
$this->template_data[ $this->index ][ $key ][ 'start_time' ] = microtime(true);
@@ -160,9 +145,9 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* End logging of cache time
*
- * @param \Smarty_Internal_Template $template cached template
+ * @param Template $template cached template
*/
- public function end_cache(Smarty_Internal_Template $template)
+ public function end_cache(Template $template)
{
$key = $this->get_key($template);
$this->template_data[ $this->index ][ $key ][ 'cache_time' ] +=
@@ -172,65 +157,52 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* Register template object
*
- * @param \Smarty_Internal_Template $template cached template
+ * @param Template $template cached template
*/
- public function register_template(Smarty_Internal_Template $template)
+ public function register_template(Template $template)
{
}
/**
* Register data object
*
- * @param \Smarty_Data $data data object
+ * @param Data $data data object
*/
- public static function register_data(Smarty_Data $data)
+ public static function register_data(Data $data)
{
}
/**
* Opens a window for the Smarty Debugging Console and display the data
*
- * @param Smarty_Internal_Template|Smarty $obj object to debug
+ * @param Template|Smarty $obj object to debug
* @param bool $full
*
* @throws \Exception
- * @throws \SmartyException
+ * @throws Exception
*/
- public function display_debug($obj, $full = false)
+ public function display_debug($obj, bool $full = false)
{
if (!$full) {
$this->offset++;
$savedIndex = $this->index;
$this->index = 9999;
}
- $smarty = $obj->_getSmartyObj();
+ $smarty = $obj->getSmarty();
// create fresh instance of smarty for displaying the debug console
// to avoid problems if the application did overload the Smarty class
$debObj = new Smarty();
// copy the working dirs from application
$debObj->setCompileDir($smarty->getCompileDir());
- // init properties by hand as user may have edited the original Smarty class
- $debObj->setPluginsDir(is_dir(dirname(__FILE__) . '/../plugins') ? dirname(__FILE__) .
- '/../plugins' : $smarty->getPluginsDir());
- $debObj->force_compile = false;
$debObj->compile_check = Smarty::COMPILECHECK_ON;
- $debObj->left_delimiter = '{';
- $debObj->right_delimiter = '}';
$debObj->security_policy = null;
$debObj->debugging = false;
$debObj->debugging_ctrl = 'NONE';
$debObj->error_reporting = E_ALL & ~E_NOTICE;
- $debObj->debug_tpl =
- isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . dirname(__FILE__) . '/../debug.tpl';
- $debObj->registered_plugins = array();
+ $debObj->debug_tpl = $smarty->debug_tpl ?? 'file:' . __DIR__ . '/debug.tpl';
$debObj->registered_resources = array();
- $debObj->registered_filters = array();
- $debObj->autoload_filters = array();
- $debObj->default_modifiers = array();
$debObj->escape_html = true;
$debObj->caching = Smarty::CACHING_OFF;
- $debObj->compile_id = null;
- $debObj->cache_id = null;
// prepare information of assigned variables
$ptr = $this->get_debug_vars($obj);
$_assigned_vars = $ptr->tpl_vars;
@@ -238,20 +210,22 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
$_config_vars = $ptr->config_vars;
ksort($_config_vars);
$debugging = $smarty->debugging;
- $_template = new Smarty_Internal_Template($debObj->debug_tpl, $debObj);
- if ($obj->_isTplObj()) {
- $_template->assign('template_name', $obj->source->type . ':' . $obj->source->name);
- }
- if ($obj->_objType === 1 || $full) {
- $_template->assign('template_data', $this->template_data[ $this->index ]);
+ $templateName = $obj->getSource()->type . ':' . $obj->getSource()->name;
+ $displayMode = $debugging === 2 || !$full;
+ $offset = $this->offset * 50;
+ $_template = $debObj->doCreateTemplate($debObj->debug_tpl);
+ if ($obj instanceof Template) {
+ $_template->assign('template_name', $templateName);
+ } elseif ($obj instanceof Smarty || $full) {
+ $_template->assign('template_data', $this->template_data[$this->index]);
} else {
$_template->assign('template_data', null);
}
$_template->assign('assigned_vars', $_assigned_vars);
$_template->assign('config_vars', $_config_vars);
$_template->assign('execution_time', microtime(true) - $smarty->start_time);
- $_template->assign('display_mode', $debugging === 2 || !$full);
- $_template->assign('offset', $this->offset * 50);
+ $_template->assign('targetWindow', $displayMode ? md5("$offset$templateName") : '__Smarty__');
+ $_template->assign('offset', $offset);
echo $_template->fetch();
if (isset($full)) {
$this->index--;
@@ -264,22 +238,16 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* Recursively gets variables from all template/data scopes
*
- * @param Smarty_Internal_Template|Smarty_Data $obj object to debug
+ * @param \Smarty\Data $obj object to debug
*
- * @return StdClass
+ * @return \StdClass
*/
- public function get_debug_vars($obj)
+ private function get_debug_vars($obj)
{
$config_vars = array();
foreach ($obj->config_vars as $key => $var) {
- $config_vars[ $key ][ 'value' ] = $var;
- if ($obj->_isTplObj()) {
- $config_vars[ $key ][ 'scope' ] = $obj->source->type . ':' . $obj->source->name;
- } elseif ($obj->_isDataObj()) {
- $tpl_vars[ $key ][ 'scope' ] = $obj->dataObjectName;
- } else {
- $config_vars[ $key ][ 'scope' ] = 'Smarty object';
- }
+ $config_vars[$key]['value'] = $var;
+ $config_vars[$key]['scope'] = get_class($obj) . ':' . spl_object_id($obj);
}
$tpl_vars = array();
foreach ($obj->tpl_vars as $key => $var) {
@@ -298,13 +266,7 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
}
}
}
- if ($obj->_isTplObj()) {
- $tpl_vars[ $key ][ 'scope' ] = $obj->source->type . ':' . $obj->source->name;
- } elseif ($obj->_isDataObj()) {
- $tpl_vars[ $key ][ 'scope' ] = $obj->dataObjectName;
- } else {
- $tpl_vars[ $key ][ 'scope' ] = 'Smarty object';
- }
+ $tpl_vars[$key]['scope'] = get_class($obj) . ':' . spl_object_id($obj);
}
if (isset($obj->parent)) {
$parent = $this->get_debug_vars($obj->parent);
@@ -320,27 +282,6 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
}
}
$config_vars = array_merge($parent->config_vars, $config_vars);
- } else {
- foreach (Smarty::$global_tpl_vars as $key => $var) {
- if (!array_key_exists($key, $tpl_vars)) {
- foreach ($var as $varkey => $varvalue) {
- if ($varkey === 'value') {
- $tpl_vars[ $key ][ $varkey ] = $varvalue;
- } else {
- if ($varkey === 'nocache') {
- if ($varvalue === true) {
- $tpl_vars[ $key ][ $varkey ] = $varvalue;
- }
- } else {
- if ($varkey !== 'scope' || $varvalue !== 0) {
- $tpl_vars[ $key ][ 'attributes' ][ $varkey ] = $varvalue;
- }
- }
- }
- }
- $tpl_vars[ $key ][ 'scope' ] = 'Global';
- }
- }
}
return (object)array('tpl_vars' => $tpl_vars, 'config_vars' => $config_vars);
}
@@ -348,31 +289,20 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* Return key into $template_data for template
*
- * @param \Smarty_Internal_Template $template template object
+ * @param Template $template template object
*
* @return string key into $template_data
*/
- private function get_key(Smarty_Internal_Template $template)
+ private function get_key(Template $template)
{
static $_is_stringy = array('string' => true, 'eval' => true);
- // calculate Uid if not already done
- if ($template->source->uid === '') {
- $template->source->filepath;
- }
- $key = $template->source->uid;
+
+ $key = $template->getSource()->uid;
if (isset($this->template_data[ $this->index ][ $key ])) {
return $key;
} else {
- if (isset($_is_stringy[ $template->source->type ])) {
- $this->template_data[ $this->index ][ $key ][ 'name' ] =
- '\'' . substr($template->source->name, 0, 25) . '...\'';
- } else {
- $this->template_data[ $this->index ][ $key ][ 'name' ] = $template->source->filepath;
- }
- $this->template_data[ $this->index ][ $key ][ 'compile_time' ] = 0;
- $this->template_data[ $this->index ][ $key ][ 'render_time' ] = 0;
- $this->template_data[ $this->index ][ $key ][ 'cache_time' ] = 0;
- $this->template_data[ $this->index ][ $key ][ 'total_time' ] = 0;
+ $this->saveTemplateData($_is_stringy, $template, $key);
+ $this->template_data[ $this->index ][ $key ][ 'total_time' ] = 0;
return $key;
}
}
@@ -380,15 +310,11 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
/**
* Ignore template
*
- * @param \Smarty_Internal_Template $template
+ * @param Template $template
*/
- public function ignore(Smarty_Internal_Template $template)
+ public function ignore(Template $template)
{
- // calculate Uid if not already done
- if ($template->source->uid === '') {
- $template->source->filepath;
- }
- $this->ignore_uid[ $template->source->uid ] = true;
+ $this->ignore_uid[$template->getSource()->uid] = true;
}
/**
@@ -422,4 +348,23 @@ class Smarty_Internal_Debug extends Smarty_Internal_Data
}
}
}
+
+ /**
+ * @param array $_is_stringy
+ * @param Template $template
+ * @param string $key
+ *
+ * @return void
+ */
+ private function saveTemplateData(array $_is_stringy, Template $template, string $key): void {
+ if (isset($_is_stringy[$template->getSource()->type])) {
+ $this->template_data[$this->index][$key]['name'] =
+ '\'' . substr($template->getSource()->name, 0, 25) . '...\'';
+ } else {
+ $this->template_data[$this->index][$key]['name'] = $template->getSource()->getResourceName();
+ }
+ $this->template_data[$this->index][$key]['compile_time'] = 0;
+ $this->template_data[$this->index][$key]['render_time'] = 0;
+ $this->template_data[$this->index][$key]['cache_time'] = 0;
+ }
}
diff --git a/src/includes/smarty-5.4.1/src/ErrorHandler.php b/src/includes/smarty-5.4.1/src/ErrorHandler.php
new file mode 100644
index 0000000..05b1cb3
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/ErrorHandler.php
@@ -0,0 +1,97 @@
+propName} where propName is undefined.
+ * @var bool
+ */
+ public $allowUndefinedProperties = true;
+
+ /**
+ * Allows {$foo.bar} where bar is unset and {$foo.bar1.bar2} where either bar1 or bar2 is unset.
+ * @var bool
+ */
+ public $allowUndefinedArrayKeys = true;
+
+ /**
+ * Allows {$foo->bar} where bar is not an object (e.g. null or false).
+ * @var bool
+ */
+ public $allowDereferencingNonObjects = true;
+
+ private $previousErrorHandler = null;
+
+ /**
+ * Enable error handler to intercept errors
+ */
+ public function activate() {
+ /*
+ Error muting is done because some people implemented custom error_handlers using
+ https://php.net/set_error_handler and for some reason did not understand the following paragraph:
+
+ It is important to remember that the standard PHP error handler is completely bypassed for the
+ error types specified by error_types unless the callback function returns FALSE.
+ error_reporting() settings will have no effect and your error handler will be called regardless -
+ however you are still able to read the current value of error_reporting and act appropriately.
+ Of particular note is that this value will be 0 if the statement that caused the error was
+ prepended by the @ error-control operator.
+ */
+ $this->previousErrorHandler = set_error_handler([$this, 'handleError']);
+ }
+
+ /**
+ * Disable error handler
+ */
+ public function deactivate() {
+ restore_error_handler();
+ $this->previousErrorHandler = null;
+ }
+
+ /**
+ * Error Handler to mute expected messages
+ *
+ * @link https://php.net/set_error_handler
+ *
+ * @param integer $errno Error level
+ * @param $errstr
+ * @param $errfile
+ * @param $errline
+ * @param $errcontext
+ *
+ * @return bool
+ */
+ public function handleError($errno, $errstr, $errfile, $errline, $errcontext = [])
+ {
+ if ($this->allowUndefinedProperties && preg_match(
+ '/^(Undefined property)/',
+ $errstr
+ )) {
+ return; // suppresses this error
+ }
+
+ if ($this->allowUndefinedArrayKeys && preg_match(
+ '/^(Undefined index|Undefined array key|Trying to access array offset on)/',
+ $errstr
+ )) {
+ return; // suppresses this error
+ }
+
+ if ($this->allowDereferencingNonObjects && preg_match(
+ '/^Attempt to read property ".+?" on/',
+ $errstr
+ )) {
+ return; // suppresses this error
+ }
+
+ // pass all other errors through to the previous error handler or to the default PHP error handler
+ return $this->previousErrorHandler ?
+ call_user_func($this->previousErrorHandler, $errno, $errstr, $errfile, $errline, $errcontext) : false;
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Exception.php b/src/includes/smarty-5.4.1/src/Exception.php
new file mode 100644
index 0000000..0f75f56
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Exception.php
@@ -0,0 +1,16 @@
+ Smarty: ' . $this->message . ' <-- ';
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Extension/BCPluginsAdapter.php b/src/includes/smarty-5.4.1/src/Extension/BCPluginsAdapter.php
new file mode 100644
index 0000000..aa0eefe
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Extension/BCPluginsAdapter.php
@@ -0,0 +1,229 @@
+smarty = $smarty;
+ }
+
+ private function findPlugin($type, $name): ?array {
+ if (null !== $plugin = $this->smarty->getRegisteredPlugin($type, $name)) {
+ return $plugin;
+ }
+
+ return null;
+ }
+
+ public function getTagCompiler(string $tag): ?\Smarty\Compile\CompilerInterface {
+
+ $plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_COMPILER, $tag);
+ if ($plugin === null) {
+ return null;
+ }
+
+ if (is_callable($plugin[0])) {
+ $callback = $plugin[0];
+ $cacheable = (bool) $plugin[1] ?? true;
+ return new TagPluginWrapper($callback, $cacheable);
+ } elseif (class_exists($plugin[0])) {
+ $compiler = new $plugin[0];
+ if ($compiler instanceof CompilerInterface) {
+ return $compiler;
+ }
+ }
+
+ return null;
+ }
+
+ public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface {
+ $plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, $functionName);
+ if ($plugin === null) {
+ return null;
+ }
+ $callback = $plugin[0];
+ $cacheable = (bool) $plugin[1] ?? true;
+
+ return new FunctionPluginWrapper($callback, $cacheable);
+
+ }
+
+ public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
+ $plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_BLOCK, $blockTagName);
+ if ($plugin === null) {
+ return null;
+ }
+ $callback = $plugin[0];
+ $cacheable = (bool) $plugin[1] ?? true;
+
+ return new BlockPluginWrapper($callback, $cacheable);
+ }
+
+ public function getModifierCallback(string $modifierName) {
+
+ $plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, $modifierName);
+ if ($plugin === null) {
+ return null;
+ }
+ return $plugin[0];
+ }
+
+ public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface {
+ $plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_MODIFIERCOMPILER, $modifier);
+ if ($plugin === null) {
+ return null;
+ }
+ $callback = $plugin[0];
+
+ return new ModifierCompilerPluginWrapper($callback);
+ }
+
+ /**
+ * @var array
+ */
+ private $preFilters = [];
+
+ public function getPreFilters(): array {
+ return $this->preFilters;
+ }
+
+ public function addPreFilter(\Smarty\Filter\FilterInterface $filter) {
+ $this->preFilters[] = $filter;
+ }
+
+ public function addCallableAsPreFilter(callable $callable, ?string $name = null) {
+ if ($name === null) {
+ $this->preFilters[] = new FilterPluginWrapper($callable);
+ } else {
+ $this->preFilters[$name] = new FilterPluginWrapper($callable);
+ }
+ }
+
+ public function removePrefilter(string $name) {
+ unset($this->preFilters[$name]);
+ }
+
+ /**
+ * @var array
+ */
+ private $postFilters = [];
+
+ public function getPostFilters(): array {
+ return $this->postFilters;
+ }
+
+ public function addPostFilter(\Smarty\Filter\FilterInterface $filter) {
+ $this->postFilters[] = $filter;
+ }
+
+ public function addCallableAsPostFilter(callable $callable, ?string $name = null) {
+ if ($name === null) {
+ $this->postFilters[] = new FilterPluginWrapper($callable);
+ } else {
+ $this->postFilters[$name] = new FilterPluginWrapper($callable);
+ }
+ }
+
+ public function removePostFilter(string $name) {
+ unset($this->postFilters[$name]);
+ }
+
+
+ /**
+ * @var array
+ */
+ private $outputFilters = [];
+
+ public function getOutputFilters(): array {
+ return $this->outputFilters;
+ }
+
+ public function addOutputFilter(\Smarty\Filter\FilterInterface $filter) {
+ $this->outputFilters[] = $filter;
+ }
+
+ public function addCallableAsOutputFilter(callable $callable, ?string $name = null) {
+ if ($name === null) {
+ $this->outputFilters[] = new FilterPluginWrapper($callable);
+ } else {
+ $this->outputFilters[$name] = new FilterPluginWrapper($callable);
+ }
+ }
+
+ public function removeOutputFilter(string $name) {
+ unset($this->outputFilters[$name]);
+ }
+
+ public function loadPluginsFromDir(string $path) {
+
+ foreach([
+ 'function',
+ 'modifier',
+ 'block',
+ 'compiler',
+ 'prefilter',
+ 'postfilter',
+ 'outputfilter',
+ ] as $type) {
+ foreach (glob($path . $type . '.?*.php') as $filename) {
+ $pluginName = $this->getPluginNameFromFilename($filename);
+ if ($pluginName !== null) {
+ require_once $filename;
+ $functionOrClassName = 'smarty_' . $type . '_' . $pluginName;
+ if (function_exists($functionOrClassName) || class_exists($functionOrClassName)) {
+ $this->smarty->registerPlugin($type, $pluginName, $functionOrClassName, true, []);
+ }
+ }
+ }
+ }
+
+ $type = 'resource';
+ foreach (glob($path . $type . '.?*.php') as $filename) {
+ $pluginName = $this->getPluginNameFromFilename($filename);
+ if ($pluginName !== null) {
+ require_once $filename;
+ if (class_exists($className = 'smarty_' . $type . '_' . $pluginName)) {
+ $this->smarty->registerResource($pluginName, new $className());
+ }
+ }
+ }
+
+ $type = 'cacheresource';
+ foreach (glob($path . $type . '.?*.php') as $filename) {
+ $pluginName = $this->getPluginNameFromFilename($filename);
+ if ($pluginName !== null) {
+ require_once $filename;
+ if (class_exists($className = 'smarty_' . $type . '_' . $pluginName)) {
+ $this->smarty->registerCacheResource($pluginName, new $className());
+ }
+ }
+ }
+
+ }
+
+ /**
+ * @param $filename
+ *
+ * @return string|null
+ */
+ private function getPluginNameFromFilename($filename) {
+ if (!preg_match('/.*\.([a-z_A-Z0-9]+)\.php$/',$filename,$matches)) {
+ return null;
+ }
+ return $matches[1];
+ }
+
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/Extension/Base.php b/src/includes/smarty-5.4.1/src/Extension/Base.php
new file mode 100644
index 0000000..b37b6ac
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Extension/Base.php
@@ -0,0 +1,41 @@
+callback = $callback;
+ $this->modifierName = $modifierName;
+ }
+
+ public function handle(...$params) {
+ try {
+ return call_user_func_array($this->callback, $params);
+ } catch (\ArgumentCountError $e) {
+ throw new Exception("Invalid number of arguments to modifier " . $this->modifierName);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/Extension/CoreExtension.php b/src/includes/smarty-5.4.1/src/Extension/CoreExtension.php
new file mode 100644
index 0000000..a7c658d
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Extension/CoreExtension.php
@@ -0,0 +1,49 @@
+modifiers[$modifier])) {
+ return $this->modifiers[$modifier];
+ }
+
+ switch ($modifier) {
+ case 'cat': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CatModifierCompiler(); break;
+ case 'count_characters': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountCharactersModifierCompiler(); break;
+ case 'count_paragraphs': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountParagraphsModifierCompiler(); break;
+ case 'count_sentences': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountSentencesModifierCompiler(); break;
+ case 'count_words': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\CountWordsModifierCompiler(); break;
+ case 'default': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\DefaultModifierCompiler(); break;
+ case 'empty': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EmptyModifierCompiler(); break;
+ case 'escape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\EscapeModifierCompiler(); break;
+ case 'from_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); break;
+ case 'indent': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IndentModifierCompiler(); break;
+ case 'is_array': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IsArrayModifierCompiler(); break;
+ case 'isset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\IssetModifierCompiler(); break;
+ case 'json_encode': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\JsonEncodeModifierCompiler(); break;
+ case 'lower': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\LowerModifierCompiler(); break;
+ case 'nl2br': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\Nl2brModifierCompiler(); break;
+ case 'noprint': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\NoPrintModifierCompiler(); break;
+ case 'raw': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RawModifierCompiler(); break;
+ case 'round': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\RoundModifierCompiler(); break;
+ case 'str_repeat': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrRepeatModifierCompiler(); break;
+ case 'string_format': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StringFormatModifierCompiler(); break;
+ case 'strip': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripModifierCompiler(); break;
+ case 'strip_tags': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StripTagsModifierCompiler(); break;
+ case 'strlen': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\StrlenModifierCompiler(); break;
+ case 'substr': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\SubstrModifierCompiler(); break;
+ case 'to_charset': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\ToCharsetModifierCompiler(); break;
+ case 'unescape': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UnescapeModifierCompiler(); break;
+ case 'upper': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\UpperModifierCompiler(); break;
+ case 'wordwrap': $this->modifiers[$modifier] = new \Smarty\Compile\Modifier\WordWrapModifierCompiler(); break;
+ }
+
+ return $this->modifiers[$modifier] ?? null;
+ }
+
+ public function getModifierCallback(string $modifierName) {
+ switch ($modifierName) {
+ case 'capitalize': return [$this, 'smarty_modifier_capitalize'];
+ case 'count': return [$this, 'smarty_modifier_count'];
+ case 'date_format': return [$this, 'smarty_modifier_date_format'];
+ case 'debug_print_var': return [$this, 'smarty_modifier_debug_print_var'];
+ case 'escape': return [$this, 'smarty_modifier_escape'];
+ case 'explode': return [$this, 'smarty_modifier_explode'];
+ case 'implode': return [$this, 'smarty_modifier_implode'];
+ case 'in_array': return [$this, 'smarty_modifier_in_array'];
+ case 'join': return [$this, 'smarty_modifier_join'];
+ case 'mb_wordwrap': return [$this, 'smarty_modifier_mb_wordwrap'];
+ case 'number_format': return [$this, 'smarty_modifier_number_format'];
+ case 'regex_replace': return [$this, 'smarty_modifier_regex_replace'];
+ case 'replace': return [$this, 'smarty_modifier_replace'];
+ case 'spacify': return [$this, 'smarty_modifier_spacify'];
+ case 'split': return [$this, 'smarty_modifier_split'];
+ case 'truncate': return [$this, 'smarty_modifier_truncate'];
+ }
+ return null;
+ }
+
+ public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface {
+
+ if (isset($this->functionHandlers[$functionName])) {
+ return $this->functionHandlers[$functionName];
+ }
+
+ switch ($functionName) {
+ case 'count': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Count(); break;
+ case 'counter': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Counter(); break;
+ case 'cycle': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Cycle(); break;
+ case 'fetch': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Fetch(); break;
+ case 'html_checkboxes': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlCheckboxes(); break;
+ case 'html_image': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlImage(); break;
+ case 'html_options': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlOptions(); break;
+ case 'html_radios': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlRadios(); break;
+ case 'html_select_date': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectDate(); break;
+ case 'html_select_time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectTime(); break;
+ case 'html_table': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlTable(); break;
+ case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break;
+ case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break;
+ }
+
+ return $this->functionHandlers[$functionName] ?? null;
+ }
+
+ public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
+
+ switch ($blockTagName) {
+ case 'textformat': $this->blockHandlers[$blockTagName] = new \Smarty\BlockHandler\TextFormat(); break;
+ }
+
+ return $this->blockHandlers[$blockTagName] ?? null;
+ }
+
+ /**
+ * Smarty spacify modifier plugin
+ * Type: modifier
+ * Name: spacify
+ * Purpose: add spaces between characters in a string
+ *
+ * @author Monte Ohrt
+ *
+ * @param string $string input string
+ * @param string $spacify_char string to insert between characters.
+ *
+ * @return string
+ */
+ public function smarty_modifier_spacify($string, $spacify_char = ' ')
+ {
+ // well… what about charsets besides latin and UTF-8?
+ return implode($spacify_char, preg_split('//' . \Smarty\Smarty::$_UTF8_MODIFIER, $string, -1, PREG_SPLIT_NO_EMPTY));
+ }
+
+ /**
+ * Smarty capitalize modifier plugin
+ * Type: modifier
+ * Name: capitalize
+ * Purpose: capitalize words in the string
+ * {@internal {$string|capitalize:true:true} is the fastest option for MBString enabled systems }}
+ *
+ * @param string $string string to capitalize
+ * @param boolean $uc_digits also capitalize "x123" to "X123"
+ * @param boolean $lc_rest capitalize first letters, lowercase all following letters "aAa" to "Aaa"
+ *
+ * @return string capitalized string
+ * @author Monte Ohrt
+ * @author Rodney Rehm
+ */
+ public function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
+ {
+ $string = (string) $string;
+
+ if ($lc_rest) {
+ // uppercase (including hyphenated words)
+ $upper_string = mb_convert_case($string, MB_CASE_TITLE, \Smarty\Smarty::$_CHARSET);
+ } else {
+ // uppercase word breaks
+ $upper_string = preg_replace_callback(
+ "!(^|[^\p{L}'])([\p{Ll}])!S" . \Smarty\Smarty::$_UTF8_MODIFIER,
+ function ($matches) {
+ return stripslashes($matches[1]) .
+ mb_convert_case(stripslashes($matches[2]), MB_CASE_UPPER, \Smarty\Smarty::$_CHARSET);
+ },
+ $string
+ );
+ }
+ // check uc_digits case
+ if (!$uc_digits) {
+ if (preg_match_all(
+ "!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . \Smarty\Smarty::$_UTF8_MODIFIER,
+ $string,
+ $matches,
+ PREG_OFFSET_CAPTURE
+ )
+ ) {
+ foreach ($matches[ 1 ] as $match) {
+ $upper_string =
+ substr_replace(
+ $upper_string,
+ mb_strtolower($match[ 0 ], \Smarty\Smarty::$_CHARSET),
+ $match[ 1 ],
+ strlen($match[ 0 ])
+ );
+ }
+ }
+ }
+ $upper_string =
+ preg_replace_callback(
+ "!((^|\s)['\"])(\w)!" . \Smarty\Smarty::$_UTF8_MODIFIER,
+ function ($matches) {
+ return stripslashes(
+ $matches[ 1 ]) . mb_convert_case(stripslashes($matches[ 3 ]),
+ MB_CASE_UPPER,
+ \Smarty\Smarty::$_CHARSET
+ );
+ },
+ $upper_string
+ );
+ return $upper_string;
+ }
+
+ /**
+ * Smarty count modifier plugin
+ * Type: modifier
+ * Name: count
+ * Purpose: counts all elements in an array or in a Countable object
+ * Input:
+ * - Countable|array: array or object to count
+ * - mode: int defaults to 0 for normal count mode, if set to 1 counts recursive
+ *
+ * @param mixed $arrayOrObject input array/object
+ * @param int $mode count mode
+ *
+ * @return int
+ */
+ public function smarty_modifier_count($arrayOrObject, $mode = 0) {
+ /*
+ * @see https://www.php.net/count
+ * > Prior to PHP 8.0.0, if the parameter was neither an array nor an object that implements the Countable interface,
+ * > 1 would be returned, unless value was null, in which case 0 would be returned.
+ */
+
+ if ($arrayOrObject instanceof \Countable || is_array($arrayOrObject)) {
+ return count($arrayOrObject, (int) $mode);
+ } elseif ($arrayOrObject === null) {
+ return 0;
+ }
+ return 1;
+ }
+
+ /**
+ * Smarty date_format modifier plugin
+ * Type: modifier
+ * Name: date_format
+ * Purpose: format datestamps via strftime
+ * Input:
+ * - string: input date string
+ * - format: strftime format for output
+ * - default_date: default date if $string is empty
+ *
+ * @author Monte Ohrt
+ *
+ * @param string $string input date string
+ * @param string $format strftime format for output
+ * @param string $default_date default date if $string is empty
+ * @param string $formatter either 'strftime' or 'auto'
+ *
+ * @return string |void
+ * @uses smarty_make_timestamp()
+ */
+ public function smarty_modifier_date_format($string, $format = null, $default_date = '', $formatter = 'auto')
+ {
+ if ($format === null) {
+ $format = \Smarty\Smarty::$_DATE_FORMAT;
+ }
+
+ if (!empty($string) && $string !== '0000-00-00' && $string !== '0000-00-00 00:00:00') {
+ $timestamp = smarty_make_timestamp($string);
+ } elseif (!empty($default_date)) {
+ $timestamp = smarty_make_timestamp($default_date);
+ } else {
+ return;
+ }
+ if ($formatter === 'strftime' || ($formatter === 'auto' && strpos($format, '%') !== false)) {
+ if (\Smarty\Smarty::$_IS_WINDOWS) {
+ $_win_from = array(
+ '%D',
+ '%h',
+ '%n',
+ '%r',
+ '%R',
+ '%t',
+ '%T'
+ );
+ $_win_to = array(
+ '%m/%d/%y',
+ '%b',
+ "\n",
+ '%I:%M:%S %p',
+ '%H:%M',
+ "\t",
+ '%H:%M:%S'
+ );
+ if (strpos($format, '%e') !== false) {
+ $_win_from[] = '%e';
+ $_win_to[] = sprintf('%\' 2d', date('j', $timestamp));
+ }
+ if (strpos($format, '%l') !== false) {
+ $_win_from[] = '%l';
+ $_win_to[] = sprintf('%\' 2d', date('h', $timestamp));
+ }
+ $format = str_replace($_win_from, $_win_to, $format);
+ }
+ // @ to suppress deprecation errors when running in PHP8.1 or higher.
+ return @strftime($format, $timestamp);
+ } else {
+ return date($format, $timestamp);
+ }
+ }
+
+ /**
+ * Smarty debug_print_var modifier plugin
+ * Type: modifier
+ * Name: debug_print_var
+ * Purpose: formats variable contents for display in the console
+ *
+ * @author Monte Ohrt
+ *
+ * @param array|object $var variable to be formatted
+ * @param int $max maximum recursion depth if $var is an array or object
+ * @param int $length maximum string length if $var is a string
+ * @param int $depth actual recursion depth
+ * @param array $objects processed objects in actual depth to prevent recursive object processing
+ *
+ * @return string
+ */
+ public function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array())
+ {
+ $_replace = array("\n" => '\n', "\r" => '\r', "\t" => '\t');
+ switch (gettype($var)) {
+ case 'array':
+ $results = 'Array (' . count($var) . ') ';
+ if ($depth === $max) {
+ break;
+ }
+ foreach ($var as $curr_key => $curr_val) {
+ $results .= ' ' . str_repeat(' ', $depth * 2) . '' . strtr($curr_key, $_replace) .
+ ' => ' .
+ $this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
+ $depth--;
+ }
+ break;
+ case 'object':
+ $object_vars = get_object_vars($var);
+ $results = '' . get_class($var) . ' Object (' . count($object_vars) . ') ';
+ if (in_array($var, $objects)) {
+ $results .= ' called recursive';
+ break;
+ }
+ if ($depth === $max) {
+ break;
+ }
+ $objects[] = $var;
+ foreach ($object_vars as $curr_key => $curr_val) {
+ $results .= ' ' . str_repeat(' ', $depth * 2) . ' ->' . strtr($curr_key, $_replace) .
+ ' = ' . $this->smarty_modifier_debug_print_var($curr_val, $max, $length, ++$depth, $objects);
+ $depth--;
+ }
+ break;
+ case 'boolean':
+ case 'NULL':
+ case 'resource':
+ if (true === $var) {
+ $results = 'true';
+ } elseif (false === $var) {
+ $results = 'false';
+ } elseif (null === $var) {
+ $results = 'null';
+ } else {
+ $results = htmlspecialchars((string)$var);
+ }
+ $results = '' . $results . ' ';
+ break;
+ case 'integer':
+ case 'float':
+ $results = htmlspecialchars((string)$var);
+ break;
+ case 'string':
+ $results = strtr($var, $_replace);
+ if (mb_strlen($var, \Smarty\Smarty::$_CHARSET) > $length) {
+ $results = mb_substr($var, 0, $length - 3, \Smarty\Smarty::$_CHARSET) . '...';
+ }
+ $results = htmlspecialchars('"' . $results . '"', ENT_QUOTES, \Smarty\Smarty::$_CHARSET);
+ break;
+ case 'unknown type':
+ default:
+ $results = strtr((string)$var, $_replace);
+ if (mb_strlen($results, \Smarty\Smarty::$_CHARSET) > $length) {
+ $results = mb_substr($results, 0, $length - 3, \Smarty\Smarty::$_CHARSET) . '...';
+ }
+ $results = htmlspecialchars($results, ENT_QUOTES, \Smarty\Smarty::$_CHARSET);
+ }
+ return $results;
+ }
+
+ /**
+ * Smarty escape modifier plugin
+ * Type: modifier
+ * Name: escape
+ * Purpose: escape string for output
+ *
+ * @author Monte Ohrt
+ *
+ * @param string $string input string
+ * @param string $esc_type escape type
+ * @param string $char_set character set, used for htmlspecialchars() or htmlentities()
+ * @param boolean $double_encode encode already encoded entitites again, used for htmlspecialchars() or htmlentities()
+ *
+ * @return string escaped input string
+ */
+ public function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true)
+ {
+ if (!$char_set) {
+ $char_set = \Smarty\Smarty::$_CHARSET;
+ }
+
+ $string = (string)$string;
+
+ switch ($esc_type) {
+ case 'html':
+ return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
+ // no break
+ case 'htmlall':
+ $string = mb_convert_encoding($string, 'UTF-8', $char_set);
+ return htmlentities($string, ENT_QUOTES, 'UTF-8', $double_encode);
+ // no break
+ case 'url':
+ return rawurlencode($string);
+ case 'urlpathinfo':
+ return str_replace('%2F', '/', rawurlencode($string));
+ case 'quotes':
+ // escape unescaped single quotes
+ return preg_replace("%(?mb_to_unicode($string, \Smarty\Smarty::$_CHARSET) as $unicode) {
+ $return .= '' . strtoupper(dechex($unicode)) . ';';
+ }
+ return $return;
+ case 'decentity':
+ $return = '';
+ foreach ($this->mb_to_unicode($string, \Smarty\Smarty::$_CHARSET) as $unicode) {
+ $return .= '' . $unicode . ';';
+ }
+ return $return;
+ case 'javascript':
+ // escape quotes and backslashes, newlines, etc.
+ return strtr(
+ $string,
+ array(
+ '\\' => '\\\\',
+ "'" => "\\'",
+ '"' => '\\"',
+ "\r" => '\\r',
+ "\n" => '\\n',
+ '' => '<\/',
+ // see https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
+ '#is',
+ $source,
+ $matches,
+ PREG_OFFSET_CAPTURE | PREG_SET_ORDER
+ )
+ ) {
+ foreach ($matches as $match) {
+ $store[] = $match[ 0 ][ 0 ];
+ $_length = strlen($match[ 0 ][ 0 ]);
+ $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
+ $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
+ $_offset += $_length - strlen($replace);
+ $_store++;
+ }
+ }
+ // Strip all HTML-Comments
+ // yes, even the ones in ]*>)|(]*>)|(]*>.*? ]*>)#is',
+ $source,
+ $matches,
+ PREG_OFFSET_CAPTURE | PREG_SET_ORDER
+ )
+ ) {
+ foreach ($matches as $match) {
+ $store[] = $match[ 0 ][ 0 ];
+ $_length = strlen($match[ 0 ][ 0 ]);
+ $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@';
+ $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] - $_offset, $_length);
+ $_offset += $_length - strlen($replace);
+ $_store++;
+ }
+ }
+ $expressions = array(// replace multiple spaces between tags by a single space
+ // can't remove them entirely, because that might break poorly implemented CSS display:inline-block elements
+ '#(:SMARTY@!@|>)\s+(?=@!@SMARTY:|<)#s' => '\1 \2',
+ // remove spaces between attributes (but not in attribute values!)
+ '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5',
+ // note: for some very weird reason trim() seems to remove spaces inside attributes.
+ // maybe a \0 byte or something is interfering?
+ '#^\s+<#Ss' => '<',
+ '#>\s+$#Ss' => '>',
+ );
+ $source = preg_replace(array_keys($expressions), array_values($expressions), $source);
+ // note: for some very weird reason trim() seems to remove spaces inside attributes.
+ // maybe a \0 byte or something is interfering?
+ // $source = trim( $source );
+ $_offset = 0;
+ if (preg_match_all('#@!@SMARTY:([0-9]+):SMARTY@!@#is', $source, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $_length = strlen($match[ 0 ][ 0 ]);
+ $replace = $store[ $match[ 1 ][ 0 ] ];
+ $source = substr_replace($source, $replace, $match[ 0 ][ 1 ] + $_offset, $_length);
+ $_offset += strlen($replace) - $_length;
+ $_store++;
+ }
+ }
+ return $source;
+ }
+
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/BCPluginWrapper.php b/src/includes/smarty-5.4.1/src/FunctionHandler/BCPluginWrapper.php
new file mode 100644
index 0000000..04af07e
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/BCPluginWrapper.php
@@ -0,0 +1,21 @@
+callback = $callback;
+ $this->cacheable = $cacheable;
+ }
+
+ public function handle($params, Template $template) {
+ $func = $this->callback;
+ return $func($params, $template);
+ }
+
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/Base.php b/src/includes/smarty-5.4.1/src/FunctionHandler/Base.php
new file mode 100644
index 0000000..7cf1963
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/Base.php
@@ -0,0 +1,21 @@
+cacheable;
+ }
+
+ public function handle($params, Template $template) {
+ // TODO: Implement handle() method.
+ }
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/Count.php b/src/includes/smarty-5.4.1/src/FunctionHandler/Count.php
new file mode 100644
index 0000000..768d809
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/Count.php
@@ -0,0 +1,36 @@
+ 2) {
+ throw new Exception("Invalid number of arguments for count. count expects 1 or 2 parameters.");
+ }
+
+ $value = $params[0];
+
+ if ($value instanceof \Countable) {
+ return $value->count();
+ }
+
+ $mode = count($params) == 2 ? (int) $params[1] : COUNT_NORMAL;
+ return count((array) $value, $mode);
+ }
+
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/Counter.php b/src/includes/smarty-5.4.1/src/FunctionHandler/Counter.php
new file mode 100644
index 0000000..b447caf
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/Counter.php
@@ -0,0 +1,61 @@
+
+ */
+class Counter extends Base {
+
+ private $counters = [];
+
+ public function handle($params, Template $template) {
+ $name = (isset($params['name'])) ? $params['name'] : 'default';
+ if (!isset($this->counters[$name])) {
+ $this->counters[$name] = ['start' => 1, 'skip' => 1, 'direction' => 'up', 'count' => 1];
+ }
+ $counter =& $this->counters[$name];
+ if (isset($params['start'])) {
+ $counter['start'] = $counter['count'] = (int)$params['start'];
+ }
+ if (!empty($params['assign'])) {
+ $counter['assign'] = $params['assign'];
+ }
+ if (isset($counter['assign'])) {
+ $template->assign($counter['assign'], $counter['count']);
+ }
+ if (isset($params['print'])) {
+ $print = (bool)$params['print'];
+ } else {
+ $print = empty($counter['assign']);
+ }
+ if ($print) {
+ $retval = $counter['count'];
+ } else {
+ $retval = null;
+ }
+ if (isset($params['skip'])) {
+ $counter['skip'] = $params['skip'];
+ }
+ if (isset($params['direction'])) {
+ $counter['direction'] = $params['direction'];
+ }
+ if ($counter['direction'] === 'down') {
+ $counter['count'] -= $counter['skip'];
+ } else {
+ $counter['count'] += $counter['skip'];
+ }
+ return $retval;
+ }
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/Cycle.php b/src/includes/smarty-5.4.1/src/FunctionHandler/Cycle.php
new file mode 100644
index 0000000..909a688
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/Cycle.php
@@ -0,0 +1,90 @@
+
+ * @author credit to Mark Priatel
+ * @author credit to Gerard
+ * @author credit to Jason Sweat
+ * @version 1.3
+ *
+ * @param array $params parameters
+ * @param Template $template template object
+ *
+ * @return string|null
+ */
+class Cycle extends Base {
+
+ public function handle($params, Template $template) {
+ static $cycle_vars;
+ $name = (empty($params['name'])) ? 'default' : $params['name'];
+ $print = !(isset($params['print'])) || (bool)$params['print'];
+ $advance = !(isset($params['advance'])) || (bool)$params['advance'];
+ $reset = isset($params['reset']) && (bool)$params['reset'];
+ if (!isset($params['values'])) {
+ if (!isset($cycle_vars[$name]['values'])) {
+ trigger_error('cycle: missing \'values\' parameter');
+ return;
+ }
+ } else {
+ if (isset($cycle_vars[$name]['values']) && $cycle_vars[$name]['values'] !== $params['values']) {
+ $cycle_vars[$name]['index'] = 0;
+ }
+ $cycle_vars[$name]['values'] = $params['values'];
+ }
+ if (isset($params['delimiter'])) {
+ $cycle_vars[$name]['delimiter'] = $params['delimiter'];
+ } elseif (!isset($cycle_vars[$name]['delimiter'])) {
+ $cycle_vars[$name]['delimiter'] = ',';
+ }
+ if (is_array($cycle_vars[$name]['values'])) {
+ $cycle_array = $cycle_vars[$name]['values'];
+ } else {
+ $cycle_array = explode($cycle_vars[$name]['delimiter'], $cycle_vars[$name]['values']);
+ }
+ if (!isset($cycle_vars[$name]['index']) || $reset) {
+ $cycle_vars[$name]['index'] = 0;
+ }
+ if (isset($params['assign'])) {
+ $print = false;
+ $template->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);
+ }
+ if ($print) {
+ $retval = $cycle_array[$cycle_vars[$name]['index']];
+ } else {
+ $retval = null;
+ }
+ if ($advance) {
+ if ($cycle_vars[$name]['index'] >= count($cycle_array) - 1) {
+ $cycle_vars[$name]['index'] = 0;
+ } else {
+ $cycle_vars[$name]['index']++;
+ }
+ }
+ return $retval;
+ }
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/Fetch.php b/src/includes/smarty-5.4.1/src/FunctionHandler/Fetch.php
new file mode 100644
index 0000000..d10ef66
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/Fetch.php
@@ -0,0 +1,203 @@
+
+ *
+ * @param array $params parameters
+ * @param Template $template template object
+ *
+ * @throws Exception
+ * @return string|null if the assign parameter is passed, Smarty assigns the result to a template variable
+ */
+class Fetch extends Base {
+
+ public function handle($params, Template $template) {
+ if (empty($params['file'])) {
+ trigger_error('[plugin] fetch parameter \'file\' cannot be empty', E_USER_NOTICE);
+ return;
+ }
+ // strip file protocol
+ if (stripos($params['file'], 'file://') === 0) {
+ $params['file'] = substr($params['file'], 7);
+ }
+ $protocol = strpos($params['file'], '://');
+ if ($protocol !== false) {
+ $protocol = strtolower(substr($params['file'], 0, $protocol));
+ }
+ if (isset($template->getSmarty()->security_policy)) {
+ if ($protocol) {
+ // remote resource (or php stream, …)
+ if (!$template->getSmarty()->security_policy->isTrustedUri($params['file'])) {
+ return;
+ }
+ } else {
+ // local file
+ if (!$template->getSmarty()->security_policy->isTrustedResourceDir($params['file'])) {
+ return;
+ }
+ }
+ }
+ $content = '';
+ if ($protocol === 'http') {
+ // http fetch
+ if ($uri_parts = parse_url($params['file'])) {
+ // set defaults
+ $host = $server_name = $uri_parts['host'];
+ $timeout = 30;
+ $accept = 'image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*';
+ $agent = 'Smarty Template Engine ' . \Smarty\Smarty::SMARTY_VERSION;
+ $referer = '';
+ $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
+ $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
+ $_is_proxy = false;
+ if (empty($uri_parts['port'])) {
+ $port = 80;
+ } else {
+ $port = $uri_parts['port'];
+ }
+ if (!empty($uri_parts['user'])) {
+ $user = $uri_parts['user'];
+ }
+ if (!empty($uri_parts['pass'])) {
+ $pass = $uri_parts['pass'];
+ }
+ // loop through parameters, setup headers
+ foreach ($params as $param_key => $param_value) {
+ switch ($param_key) {
+ case 'file':
+ case 'assign':
+ case 'assign_headers':
+ break;
+ case 'user':
+ if (!empty($param_value)) {
+ $user = $param_value;
+ }
+ break;
+ case 'pass':
+ if (!empty($param_value)) {
+ $pass = $param_value;
+ }
+ break;
+ case 'accept':
+ if (!empty($param_value)) {
+ $accept = $param_value;
+ }
+ break;
+ case 'header':
+ if (!empty($param_value)) {
+ if (!preg_match('![\w\d-]+: .+!', $param_value)) {
+ trigger_error("[plugin] invalid header format '{$param_value}'", E_USER_NOTICE);
+ return;
+ } else {
+ $extra_headers[] = $param_value;
+ }
+ }
+ break;
+ case 'proxy_host':
+ if (!empty($param_value)) {
+ $proxy_host = $param_value;
+ }
+ break;
+ case 'proxy_port':
+ if (!preg_match('!\D!', $param_value)) {
+ $proxy_port = (int)$param_value;
+ } else {
+ trigger_error("[plugin] invalid value for attribute '{$param_key }'", E_USER_NOTICE);
+ return;
+ }
+ break;
+ case 'agent':
+ if (!empty($param_value)) {
+ $agent = $param_value;
+ }
+ break;
+ case 'referer':
+ if (!empty($param_value)) {
+ $referer = $param_value;
+ }
+ break;
+ case 'timeout':
+ if (!preg_match('!\D!', $param_value)) {
+ $timeout = (int)$param_value;
+ } else {
+ trigger_error("[plugin] invalid value for attribute '{$param_key}'", E_USER_NOTICE);
+ return;
+ }
+ break;
+ default:
+ trigger_error("[plugin] unrecognized attribute '{$param_key}'", E_USER_NOTICE);
+ return;
+ }
+ }
+ if (!empty($proxy_host) && !empty($proxy_port)) {
+ $_is_proxy = true;
+ $fp = fsockopen($proxy_host, $proxy_port, $errno, $errstr, $timeout);
+ } else {
+ $fp = fsockopen($server_name, $port, $errno, $errstr, $timeout);
+ }
+ if (!$fp) {
+ trigger_error("[plugin] unable to fetch: $errstr ($errno)", E_USER_NOTICE);
+ return;
+ } else {
+ if ($_is_proxy) {
+ fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
+ } else {
+ fputs($fp, "GET $uri HTTP/1.0\r\n");
+ }
+ if (!empty($host)) {
+ fputs($fp, "Host: $host\r\n");
+ }
+ if (!empty($accept)) {
+ fputs($fp, "Accept: $accept\r\n");
+ }
+ if (!empty($agent)) {
+ fputs($fp, "User-Agent: $agent\r\n");
+ }
+ if (!empty($referer)) {
+ fputs($fp, "Referer: $referer\r\n");
+ }
+ if (isset($extra_headers) && is_array($extra_headers)) {
+ foreach ($extra_headers as $curr_header) {
+ fputs($fp, $curr_header . "\r\n");
+ }
+ }
+ if (!empty($user) && !empty($pass)) {
+ fputs($fp, 'Authorization: BASIC ' . base64_encode("$user:$pass") . "\r\n");
+ }
+ fputs($fp, "\r\n");
+ while (!feof($fp)) {
+ $content .= fgets($fp, 4096);
+ }
+ fclose($fp);
+ $csplit = preg_split("!\r\n\r\n!", $content, 2);
+ $content = $csplit[1];
+ if (!empty($params['assign_headers'])) {
+ $template->assign($params['assign_headers'], preg_split("!\r\n!", $csplit[0]));
+ }
+ }
+ } else {
+ trigger_error("[plugin fetch] unable to parse URL, check syntax", E_USER_NOTICE);
+ return;
+ }
+ } else {
+ $content = @file_get_contents($params['file']);
+ if ($content === false) {
+ throw new Exception("{fetch} cannot read resource '" . $params['file'] . "'");
+ }
+ }
+ if (!empty($params['assign'])) {
+ $template->assign($params['assign'], $content);
+ } else {
+ return $content;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/FunctionHandlerInterface.php b/src/includes/smarty-5.4.1/src/FunctionHandler/FunctionHandlerInterface.php
new file mode 100644
index 0000000..ce77e13
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/FunctionHandlerInterface.php
@@ -0,0 +1,10 @@
+__toString();
+ } else {
+ trigger_error(
+ 'value is an object of class \'' . get_class($value) .
+ '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ return '';
+ }
+ } else {
+ $value = (string)$value;
+ }
+ if (is_object($output)) {
+ if (method_exists($output, '__toString')) {
+ $output = (string)$output->__toString();
+ } else {
+ trigger_error(
+ 'output is an object of class \'' . get_class($output) .
+ '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ return '';
+ }
+ } else {
+ $output = (string)$output;
+ }
+ if ($labels) {
+ if ($label_ids) {
+ $_id = smarty_function_escape_special_chars(
+ preg_replace(
+ '![^\w\-\.]!' . \Smarty\Smarty::$_UTF8_MODIFIER,
+ '_',
+ $name . '_' . $value
+ )
+ );
+ $_output .= '';
+ } else {
+ $_output .= '';
+ }
+ }
+ $name = smarty_function_escape_special_chars($name);
+ $value = smarty_function_escape_special_chars($value);
+ if ($escape) {
+ $output = smarty_function_escape_special_chars($output);
+ }
+ $_output .= ' ' . $output;
+ if ($labels) {
+ $_output .= ' ';
+ }
+ $_output .= $separator;
+ return $_output;
+ }
+
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlCheckboxes.php b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlCheckboxes.php
new file mode 100644
index 0000000..45ecc40
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlCheckboxes.php
@@ -0,0 +1,189 @@
+' output=$names}
+ * {html_checkboxes values=$ids checked=$checked separator=' ' output=$names}
+ *
+ * Params:
+ *
+ * - name (optional) - string default "checkbox"
+ * - values (required) - array
+ * - options (optional) - associative array
+ * - checked (optional) - array default not set
+ * - separator (optional) - ie or
+ * - output (optional) - the output next to each checkbox
+ * - assign (optional) - assign the output as an array to this variable
+ * - escape (optional) - escape the content (not value), defaults to true
+ *
+ * @author Christopher Kvarme
+ * @author credits to Monte Ohrt
+ * @version 1.0
+ *
+ * @param array $params parameters
+ * @param Template $template template object
+ *
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ * @throws \Smarty\Exception
+ */
+class HtmlCheckboxes extends HtmlBase {
+
+ public function handle($params, Template $template) {
+ $name = 'checkbox';
+ $values = null;
+ $options = null;
+ $selected = [];
+ $separator = '';
+ $escape = true;
+ $labels = true;
+ $label_ids = false;
+ $output = null;
+ $extra = '';
+ foreach ($params as $_key => $_val) {
+ switch ($_key) {
+ case 'name':
+ case 'separator':
+ $$_key = (string)$_val;
+ break;
+ case 'escape':
+ case 'labels':
+ case 'label_ids':
+ $$_key = (bool)$_val;
+ break;
+ case 'options':
+ $$_key = (array)$_val;
+ break;
+ case 'values':
+ case 'output':
+ $$_key = array_values((array)$_val);
+ break;
+ case 'checked':
+ case 'selected':
+ if (is_array($_val)) {
+ $selected = [];
+ foreach ($_val as $_sel) {
+ if (is_object($_sel)) {
+ if (method_exists($_sel, '__toString')) {
+ $_sel = smarty_function_escape_special_chars((string)$_sel->__toString());
+ } else {
+ trigger_error(
+ 'html_checkboxes: selected attribute contains an object of class \'' .
+ get_class($_sel) . '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ continue;
+ }
+ } else {
+ $_sel = smarty_function_escape_special_chars((string)$_sel);
+ }
+ $selected[$_sel] = true;
+ }
+ } elseif (is_object($_val)) {
+ if (method_exists($_val, '__toString')) {
+ $selected = smarty_function_escape_special_chars((string)$_val->__toString());
+ } else {
+ trigger_error(
+ 'html_checkboxes: selected attribute is an object of class \'' . get_class($_val) .
+ '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ }
+ } else {
+ $selected = smarty_function_escape_special_chars((string)$_val);
+ }
+ break;
+ case 'checkboxes':
+ trigger_error(
+ 'html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead',
+ E_USER_WARNING
+ );
+ $options = (array)$_val;
+ break;
+ case 'strict':
+ case 'assign':
+ break;
+ case 'disabled':
+ case 'readonly':
+ if (!empty($params['strict'])) {
+ if (!is_scalar($_val)) {
+ trigger_error(
+ "html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute",
+ E_USER_NOTICE
+ );
+ }
+ if ($_val === true || $_val === $_key) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"';
+ }
+ break;
+ }
+ // omit break; to fall through!
+ // no break
+ default:
+ if (!is_array($_val)) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+ } else {
+ trigger_error("html_checkboxes: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+ if (!isset($options) && !isset($values)) {
+ return '';
+ } /* raise error here? */
+ $_html_result = [];
+ if (isset($options)) {
+ foreach ($options as $_key => $_val) {
+ $_html_result[] =
+ $this->getHtmlForInput(
+ 'checkbox',
+ $name,
+ $_key,
+ $_val,
+ true,
+ $selected,
+ $extra,
+ $separator,
+ $labels,
+ $label_ids,
+ $escape
+ );
+ }
+ } else {
+ foreach ($values as $_i => $_key) {
+ $_val = isset($output[$_i]) ? $output[$_i] : '';
+ $_html_result[] =
+ $this->getHtmlForInput(
+ 'checkbox',
+ $name,
+ $_key,
+ $_val,
+ true,
+ $selected,
+ $extra,
+ $separator,
+ $labels,
+ $label_ids,
+ $escape
+ );
+ }
+ }
+ if (!empty($params['assign'])) {
+ $template->assign($params['assign'], $_html_result);
+ } else {
+ return implode("\n", $_html_result);
+ }
+ }
+
+}
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlImage.php b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlImage.php
new file mode 100644
index 0000000..9cb0874
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlImage.php
@@ -0,0 +1,149 @@
+
+ * Params:
+ *
+ * - file - (required) - file (and path) of image
+ * - height - (optional) - image height (default actual height)
+ * - width - (optional) - image width (default actual width)
+ * - basedir - (optional) - base directory for absolute paths, default is environment variable DOCUMENT_ROOT
+ * - path_prefix - prefix for path output (optional, default empty)
+ *
+ * @author Monte Ohrt
+ * @author credits to Duda
+ * @version 1.0
+ *
+ * @param array $params parameters
+ * @param Template $template template object
+ *
+ * @throws Exception
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+class HtmlImage extends Base {
+
+ public function handle($params, Template $template) {
+ $alt = '';
+ $file = '';
+ $height = '';
+ $width = '';
+ $extra = '';
+ $prefix = '';
+ $suffix = '';
+ $path_prefix = '';
+ $basedir = $_SERVER['DOCUMENT_ROOT'] ?? '';
+ foreach ($params as $_key => $_val) {
+ switch ($_key) {
+ case 'file':
+ case 'height':
+ case 'width':
+ case 'dpi':
+ case 'path_prefix':
+ case 'basedir':
+ $$_key = $_val;
+ break;
+ case 'alt':
+ if (!is_array($_val)) {
+ $$_key = smarty_function_escape_special_chars($_val);
+ } else {
+ throw new Exception(
+ "html_image: extra attribute '{$_key}' cannot be an array",
+ E_USER_NOTICE
+ );
+ }
+ break;
+ case 'link':
+ case 'href':
+ $prefix = '';
+ $suffix = ' ';
+ break;
+ default:
+ if (!is_array($_val)) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+ } else {
+ throw new Exception(
+ "html_image: extra attribute '{$_key}' cannot be an array",
+ E_USER_NOTICE
+ );
+ }
+ break;
+ }
+ }
+ if (empty($file)) {
+ trigger_error('html_image: missing \'file\' parameter', E_USER_NOTICE);
+ return;
+ }
+ if ($file[0] === '/') {
+ $_image_path = $basedir . $file;
+ } else {
+ $_image_path = $file;
+ }
+ // strip file protocol
+ if (stripos($params['file'], 'file://') === 0) {
+ $params['file'] = substr($params['file'], 7);
+ }
+ $protocol = strpos($params['file'], '://');
+ if ($protocol !== false) {
+ $protocol = strtolower(substr($params['file'], 0, $protocol));
+ }
+ if (isset($template->getSmarty()->security_policy)) {
+ if ($protocol) {
+ // remote resource (or php stream, …)
+ if (!$template->getSmarty()->security_policy->isTrustedUri($params['file'])) {
+ return;
+ }
+ } else {
+ // local file
+ if (!$template->getSmarty()->security_policy->isTrustedResourceDir($_image_path)) {
+ return;
+ }
+ }
+ }
+ if (!isset($params['width']) || !isset($params['height'])) {
+ // FIXME: (rodneyrehm) getimagesize() loads the complete file off a remote resource, use custom [jpg,png,gif]header reader!
+ if (!$_image_data = @getimagesize($_image_path)) {
+ if (!file_exists($_image_path)) {
+ trigger_error("html_image: unable to find '{$_image_path}'", E_USER_NOTICE);
+ return;
+ } elseif (!is_readable($_image_path)) {
+ trigger_error("html_image: unable to read '{$_image_path}'", E_USER_NOTICE);
+ return;
+ } else {
+ trigger_error("html_image: '{$_image_path}' is not a valid image file", E_USER_NOTICE);
+ return;
+ }
+ }
+ if (!isset($params['width'])) {
+ $width = $_image_data[0];
+ }
+ if (!isset($params['height'])) {
+ $height = $_image_data[1];
+ }
+ }
+ if (isset($params['dpi'])) {
+ if (strstr($_SERVER['HTTP_USER_AGENT'], 'Mac')) {
+ // FIXME: (rodneyrehm) wrong dpi assumption
+ // don't know who thought this up… even if it was true in 1998, it's definitely wrong in 2011.
+ $dpi_default = 72;
+ } else {
+ $dpi_default = 96;
+ }
+ $_resize = $dpi_default / $params['dpi'];
+ $width = round($width * $_resize);
+ $height = round($height * $_resize);
+ }
+ return $prefix . ' ' . $suffix;
+ }
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlOptions.php b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlOptions.php
new file mode 100644
index 0000000..5346738
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlOptions.php
@@ -0,0 +1,223 @@
+ tags generated from
+ * the passed parameters
+ * Params:
+ *
+ * - name (optional) - string default "select"
+ * - values (required) - if no options supplied) - array
+ * - options (required) - if no values supplied) - associative array
+ * - selected (optional) - string default not set
+ * - output (required) - if not options supplied) - array
+ * - id (optional) - string default not set
+ * - class (optional) - string default not set
+ *
+ * @author Monte Ohrt
+ * @author Ralf Strehle (minor optimization)
+ *
+ * @param array $params parameters
+ *
+ * @param \Smarty\Template $template
+ *
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ * @throws \Smarty\Exception
+ */
+class HtmlOptions extends Base {
+
+ public function handle($params, Template $template) {
+ $name = null;
+ $values = null;
+ $options = null;
+ $selected = null;
+ $output = null;
+ $id = null;
+ $class = null;
+ $extra = '';
+ foreach ($params as $_key => $_val) {
+ switch ($_key) {
+ case 'name':
+ case 'class':
+ case 'id':
+ $$_key = (string)$_val;
+ break;
+ case 'options':
+ $options = (array)$_val;
+ break;
+ case 'values':
+ case 'output':
+ $$_key = array_values((array)$_val);
+ break;
+ case 'selected':
+ if (is_array($_val)) {
+ $selected = [];
+ foreach ($_val as $_sel) {
+ if (is_object($_sel)) {
+ if (method_exists($_sel, '__toString')) {
+ $_sel = smarty_function_escape_special_chars((string)$_sel->__toString());
+ } else {
+ trigger_error(
+ 'html_options: selected attribute contains an object of class \'' .
+ get_class($_sel) . '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ continue;
+ }
+ } else {
+ $_sel = smarty_function_escape_special_chars((string)$_sel);
+ }
+ $selected[$_sel] = true;
+ }
+ } elseif (is_object($_val)) {
+ if (method_exists($_val, '__toString')) {
+ $selected = smarty_function_escape_special_chars((string)$_val->__toString());
+ } else {
+ trigger_error(
+ 'html_options: selected attribute is an object of class \'' . get_class($_val) .
+ '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ }
+ } else {
+ $selected = smarty_function_escape_special_chars((string)$_val);
+ }
+ break;
+ case 'strict':
+ break;
+ case 'disabled':
+ case 'readonly':
+ if (!empty($params['strict'])) {
+ if (!is_scalar($_val)) {
+ trigger_error(
+ "html_options: {$_key} attribute must be a scalar, only boolean true or string '{$_key}' will actually add the attribute",
+ E_USER_NOTICE
+ );
+ }
+ if ($_val === true || $_val === $_key) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"';
+ }
+ break;
+ }
+ // omit break; to fall through!
+ // no break
+ default:
+ if (!is_array($_val)) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+ } else {
+ trigger_error("html_options: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+ if (!isset($options) && !isset($values)) {
+ /* raise error here? */
+ return '';
+ }
+ $_html_result = '';
+ $_idx = 0;
+ if (isset($options)) {
+ foreach ($options as $_key => $_val) {
+ $_html_result .= $this->output($_key, $_val, $selected, $id, $class, $_idx);
+ }
+ } else {
+ foreach ($values as $_i => $_key) {
+ $_val = $output[$_i] ?? '';
+ $_html_result .= $this->output($_key, $_val, $selected, $id, $class, $_idx);
+ }
+ }
+ if (!empty($name)) {
+ $_html_class = !empty($class) ? ' class="' . $class . '"' : '';
+ $_html_id = !empty($id) ? ' id="' . $id . '"' : '';
+ $_html_result =
+ '' . "\n" . $_html_result .
+ ' ' . "\n";
+ }
+ return $_html_result;
+ }
+
+
+ /**
+ * @param $key
+ * @param $value
+ * @param $selected
+ * @param $id
+ * @param $class
+ * @param $idx
+ *
+ * @return string
+ */
+ private function output($key, $value, $selected, $id, $class, &$idx)
+ {
+ if (!is_array($value)) {
+ $_key = smarty_function_escape_special_chars($key);
+ $_html_result = '__toString());
+ } else {
+ trigger_error(
+ 'html_options: value is an object of class \'' . get_class($value) .
+ '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ return '';
+ }
+ } else {
+ $value = smarty_function_escape_special_chars((string)$value);
+ }
+ $_html_result .= $_html_class . $_html_id . '>' . $value . ' ' . "\n";
+ $idx++;
+ } else {
+ $_idx = 0;
+ $_html_result =
+ $this->getHtmlForOptGroup(
+ $key,
+ $value,
+ $selected,
+ !empty($id) ? ($id . '-' . $idx) : null,
+ $class,
+ $_idx
+ );
+ $idx++;
+ }
+ return $_html_result;
+ }
+
+ /**
+ * @param $key
+ * @param $values
+ * @param $selected
+ * @param $id
+ * @param $class
+ * @param $idx
+ *
+ * @return string
+ */
+ private function getHtmlForOptGroup($key, $values, $selected, $id, $class, &$idx)
+ {
+ $optgroup_html = '' . "\n";
+ foreach ($values as $key => $value) {
+ $optgroup_html .= $this->output($key, $value, $selected, $id, $class, $idx);
+ }
+ $optgroup_html .= " \n";
+ return $optgroup_html;
+ }
+
+}
+
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlRadios.php b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlRadios.php
new file mode 100644
index 0000000..544c5c7
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlRadios.php
@@ -0,0 +1,174 @@
+ or
+ * - output (optional) - the output next to each radio button
+ * - assign (optional) - assign the output as an array to this variable
+ * - escape (optional) - escape the content (not value), defaults to true
+ *
+ * Examples:
+ *
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator=' ' output=$names}
+ * {html_radios values=$ids checked=$checked separator=' ' output=$names}
+ *
+ * @author Christopher Kvarme
+ * @author credits to Monte Ohrt
+ * @version 1.0
+ *
+ * @param array $params parameters
+ * @param Template $template template object
+ *
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ * @throws \Smarty\Exception
+ */
+class HtmlRadios extends HtmlBase {
+
+ public function handle($params, Template $template) {
+ $name = 'radio';
+ $values = null;
+ $options = null;
+ $selected = null;
+ $separator = '';
+ $escape = true;
+ $labels = true;
+ $label_ids = false;
+ $output = null;
+ $extra = '';
+ foreach ($params as $_key => $_val) {
+ switch ($_key) {
+ case 'name':
+ case 'separator':
+ $$_key = (string)$_val;
+ break;
+ case 'checked':
+ case 'selected':
+ if (is_array($_val)) {
+ trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
+ } elseif (is_object($_val)) {
+ if (method_exists($_val, '__toString')) {
+ $selected = smarty_function_escape_special_chars((string)$_val->__toString());
+ } else {
+ trigger_error(
+ 'html_radios: selected attribute is an object of class \'' . get_class($_val) .
+ '\' without __toString() method',
+ E_USER_NOTICE
+ );
+ }
+ } else {
+ $selected = (string)$_val;
+ }
+ break;
+ case 'escape':
+ case 'labels':
+ case 'label_ids':
+ $$_key = (bool)$_val;
+ break;
+ case 'options':
+ $$_key = (array)$_val;
+ break;
+ case 'values':
+ case 'output':
+ $$_key = array_values((array)$_val);
+ break;
+ case 'radios':
+ trigger_error(
+ 'html_radios: the use of the "radios" attribute is deprecated, use "options" instead',
+ E_USER_WARNING
+ );
+ $options = (array)$_val;
+ break;
+ case 'strict':
+ case 'assign':
+ break;
+ case 'disabled':
+ case 'readonly':
+ if (!empty($params['strict'])) {
+ if (!is_scalar($_val)) {
+ trigger_error(
+ "html_options: {$_key} attribute must be a scalar, only boolean true or string '$_key' will actually add the attribute",
+ E_USER_NOTICE
+ );
+ }
+ if ($_val === true || $_val === $_key) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_key) . '"';
+ }
+ break;
+ }
+ // omit break; to fall through!
+ // no break
+ default:
+ if (!is_array($_val)) {
+ $extra .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_val) . '"';
+ } else {
+ trigger_error("html_radios: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+ if (!isset($options) && !isset($values)) {
+ /* raise error here? */
+ return '';
+ }
+ $_html_result = [];
+ if (isset($options)) {
+ foreach ($options as $_key => $_val) {
+ $_html_result[] =
+ $this->getHtmlForInput(
+ 'radio',
+ $name,
+ $_key,
+ $_val,
+ false,
+ $selected,
+ $extra,
+ $separator,
+ $labels,
+ $label_ids,
+ $escape
+ );
+ }
+ } else {
+ foreach ($values as $_i => $_key) {
+ $_val = $output[$_i] ?? '';
+ $_html_result[] =
+ $this->getHtmlForInput(
+ 'radio',
+ $name,
+ $_key,
+ $_val,
+ false,
+ $selected,
+ $extra,
+ $separator,
+ $labels,
+ $label_ids,
+ $escape
+ );
+ }
+ }
+ if (!empty($params['assign'])) {
+ $template->assign($params['assign'], $_html_result);
+ } else {
+ return implode("\n", $_html_result);
+ }
+ }
+
+
+}
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlSelectDate.php b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlSelectDate.php
new file mode 100644
index 0000000..a6acfb7
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlSelectDate.php
@@ -0,0 +1,381 @@
+
+ * @author Rodney Rehm
+ *
+ * @param array $params parameters
+ *
+ * @param \Smarty\Template $template
+ *
+ * @return string
+ * @throws \Smarty\Exception
+ */
+class HtmlSelectDate extends Base {
+
+ public function handle($params, Template $template) {
+ // generate timestamps used for month names only
+ static $_month_timestamps = null;
+ static $_current_year = null;
+ if ($_month_timestamps === null) {
+ $_current_year = date('Y');
+ $_month_timestamps = [];
+ for ($i = 1; $i <= 12; $i++) {
+ $_month_timestamps[$i] = mktime(0, 0, 0, $i, 1, 2000);
+ }
+ }
+ /* Default values. */
+ $prefix = 'Date_';
+ $start_year = null;
+ $end_year = null;
+ $display_days = true;
+ $display_months = true;
+ $display_years = true;
+ $month_format = '%B';
+ /* Write months as numbers by default GL */
+ $month_value_format = '%m';
+ $day_format = '%02d';
+ /* Write day values using this format MB */
+ $day_value_format = '%d';
+ $year_as_text = false;
+ /* Display years in reverse order? Ie. 2000,1999,.... */
+ $reverse_years = false;
+ /* Should the select boxes be part of an array when returned from PHP?
+ e.g. setting it to "birthday", would create "birthday[Day]",
+ "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
+ $field_array = null;
+ /* 's of the different tags.
+ If not set, uses default dropdown. */
+ $day_size = null;
+ $month_size = null;
+ $year_size = null;
+ /* Unparsed attributes common to *ALL* the / tags.
+ An example might be in the template: all_extra ='class ="foo"'. */
+ $all_extra = null;
+ /* Separate attributes for the tags. */
+ $day_extra = null;
+ $month_extra = null;
+ $year_extra = null;
+ /* Order in which to display the fields.
+ "D" -> day, "M" -> month, "Y" -> year. */
+ $field_order = 'MDY';
+ /* String printed between the different fields. */
+ $field_separator = "\n";
+ $option_separator = "\n";
+ $time = null;
+
+ // $all_empty = null;
+ // $day_empty = null;
+ // $month_empty = null;
+ // $year_empty = null;
+ $extra_attrs = '';
+ $all_id = null;
+ $day_id = null;
+ $month_id = null;
+ $year_id = null;
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ case 'time':
+ $$_key = $_value; // we'll handle conversion below
+ break;
+ case 'month_names':
+ if (is_array($_value) && count($_value) === 12) {
+ $$_key = $_value;
+ } else {
+ trigger_error('html_select_date: month_names must be an array of 12 strings', E_USER_NOTICE);
+ }
+ break;
+ case 'prefix':
+ case 'field_array':
+ case 'start_year':
+ case 'end_year':
+ case 'day_format':
+ case 'day_value_format':
+ case 'month_format':
+ case 'month_value_format':
+ case 'day_size':
+ case 'month_size':
+ case 'year_size':
+ case 'all_extra':
+ case 'day_extra':
+ case 'month_extra':
+ case 'year_extra':
+ case 'field_order':
+ case 'field_separator':
+ case 'option_separator':
+ case 'all_empty':
+ case 'month_empty':
+ case 'day_empty':
+ case 'year_empty':
+ case 'all_id':
+ case 'month_id':
+ case 'day_id':
+ case 'year_id':
+ $$_key = (string)$_value;
+ break;
+ case 'display_days':
+ case 'display_months':
+ case 'display_years':
+ case 'year_as_text':
+ case 'reverse_years':
+ $$_key = (bool)$_value;
+ break;
+ default:
+ if (!is_array($_value)) {
+ $extra_attrs .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_value) . '"';
+ } else {
+ trigger_error("html_select_date: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+ // Note: date() is faster than strftime()
+ // Note: explode(date()) is faster than date() date() date()
+
+ if (isset($time) && is_array($time)) {
+ if (isset($time[$prefix . 'Year'])) {
+ // $_REQUEST[$field_array] given
+ foreach ([
+ 'Y' => 'Year',
+ 'm' => 'Month',
+ 'd' => 'Day'
+ ] as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName =
+ $time[$prefix . $_elementName] ?? date($_elementKey);
+ }
+ } elseif (isset($time[$field_array][$prefix . 'Year'])) {
+ // $_REQUEST given
+ foreach ([
+ 'Y' => 'Year',
+ 'm' => 'Month',
+ 'd' => 'Day'
+ ] as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName = $time[$field_array][$prefix . $_elementName] ?? date($_elementKey);
+ }
+ } else {
+ // no date found, use NOW
+ [$_year, $_month, $_day] = explode('-', date('Y-m-d'));
+ }
+ } elseif (isset($time) && preg_match("/(\d*)-(\d*)-(\d*)/", $time, $matches)) {
+ $_year = $_month = $_day = null;
+ if ($matches[1] > '') {
+ $_year = (int)$matches[1];
+ }
+ if ($matches[2] > '') {
+ $_month = (int)$matches[2];
+ }
+ if ($matches[3] > '') {
+ $_day = (int)$matches[3];
+ }
+ } elseif ($time === null) {
+ if (array_key_exists('time', $params)) {
+ $_year = $_month = $_day = null;
+ } else {
+ [$_year, $_month, $_day] = explode('-', date('Y-m-d'));
+ }
+ } else {
+ $time = smarty_make_timestamp($time);
+ [$_year, $_month, $_day] = explode('-', date('Y-m-d', $time));
+ }
+
+ // make syntax "+N" or "-N" work with $start_year and $end_year
+ // Note preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match) is slower than trim+substr
+ foreach ([
+ 'start',
+ 'end'
+ ] as $key) {
+ $key .= '_year';
+ $t = $$key;
+ if ($t === null) {
+ $$key = (int)$_current_year;
+ } elseif ($t[0] === '+') {
+ $$key = (int)($_current_year + (int)trim(substr($t, 1)));
+ } elseif ($t[0] === '-') {
+ $$key = (int)($_current_year - (int)trim(substr($t, 1)));
+ } else {
+ $$key = (int)$$key;
+ }
+ }
+ // flip for ascending or descending
+ if (($start_year > $end_year && !$reverse_years) || ($start_year < $end_year && $reverse_years)) {
+ $t = $end_year;
+ $end_year = $start_year;
+ $start_year = $t;
+ }
+ // generate year or
+ if ($display_years) {
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Year]') : ($prefix . 'Year');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($year_extra) {
+ $_extra .= ' ' . $year_extra;
+ }
+ if ($year_as_text) {
+ $_html_years =
+ ' ';
+ } else {
+ $_html_years = '' . $option_separator;
+ if (isset($year_empty) || isset($all_empty)) {
+ $_html_years .= '' . (isset($year_empty) ? $year_empty : $all_empty) . ' ' .
+ $option_separator;
+ }
+ $op = $start_year > $end_year ? -1 : 1;
+ for ($i = $start_year; $op > 0 ? $i <= $end_year : $i >= $end_year; $i += $op) {
+ $_html_years .= '' . $i .
+ ' ' . $option_separator;
+ }
+ $_html_years .= ' ';
+ }
+ }
+ // generate month or
+ if ($display_months) {
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Month]') : ($prefix . 'Month');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($month_extra) {
+ $_extra .= ' ' . $month_extra;
+ }
+ $_html_months = '' . $option_separator;
+ if (isset($month_empty) || isset($all_empty)) {
+ $_html_months .= '' . (isset($month_empty) ? $month_empty : $all_empty) . ' ' .
+ $option_separator;
+ }
+ for ($i = 1; $i <= 12; $i++) {
+ $_val = sprintf('%02d', $i);
+ $_text = isset($month_names) ? smarty_function_escape_special_chars($month_names[$i]) :
+ ($month_format === '%m' ? $_val : @strftime($month_format, $_month_timestamps[$i]));
+ $_value = $month_value_format === '%m' ? $_val : @strftime($month_value_format, $_month_timestamps[$i]);
+ $_html_months .= '' . $_text . ' ' . $option_separator;
+ }
+ $_html_months .= ' ';
+ }
+ // generate day or
+ if ($display_days) {
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Day]') : ($prefix . 'Day');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($day_extra) {
+ $_extra .= ' ' . $day_extra;
+ }
+ $_html_days = '' . $option_separator;
+ if (isset($day_empty) || isset($all_empty)) {
+ $_html_days .= '' . (isset($day_empty) ? $day_empty : $all_empty) . ' ' .
+ $option_separator;
+ }
+ for ($i = 1; $i <= 31; $i++) {
+ $_val = sprintf('%02d', $i);
+ $_text = $day_format === '%02d' ? $_val : sprintf($day_format, $i);
+ $_value = $day_value_format === '%02d' ? $_val : sprintf($day_value_format, $i);
+ $_html_days .= '' .
+ $_text . ' ' . $option_separator;
+ }
+ $_html_days .= ' ';
+ }
+ // order the fields for output
+ $_html = '';
+ for ($i = 0; $i <= 2; $i++) {
+ switch ($field_order[$i]) {
+ case 'Y':
+ case 'y':
+ if (isset($_html_years)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $_html_years;
+ }
+ break;
+ case 'm':
+ case 'M':
+ if (isset($_html_months)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $_html_months;
+ }
+ break;
+ case 'd':
+ case 'D':
+ if (isset($_html_days)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $_html_days;
+ }
+ break;
+ }
+ }
+ return $_html;
+ }
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlSelectTime.php b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlSelectTime.php
new file mode 100644
index 0000000..40679c1
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlSelectTime.php
@@ -0,0 +1,334 @@
+
+ * @author Monte Ohrt
+ *
+ * @param array $params parameters
+ *
+ * @param \Smarty\Template $template
+ *
+ * @return string
+ * @uses smarty_make_timestamp()
+ * @throws \Smarty\Exception
+ */
+class HtmlSelectTime extends Base {
+
+ public function handle($params, Template $template) {
+ $prefix = 'Time_';
+ $field_array = null;
+ $field_separator = "\n";
+ $option_separator = "\n";
+ $time = null;
+ $display_hours = true;
+ $display_minutes = true;
+ $display_seconds = true;
+ $display_meridian = true;
+ $hour_format = '%02d';
+ $hour_value_format = '%02d';
+ $minute_format = '%02d';
+ $minute_value_format = '%02d';
+ $second_format = '%02d';
+ $second_value_format = '%02d';
+ $hour_size = null;
+ $minute_size = null;
+ $second_size = null;
+ $meridian_size = null;
+ $all_empty = null;
+ $hour_empty = null;
+ $minute_empty = null;
+ $second_empty = null;
+ $meridian_empty = null;
+ $all_id = null;
+ $hour_id = null;
+ $minute_id = null;
+ $second_id = null;
+ $meridian_id = null;
+ $use_24_hours = true;
+ $minute_interval = 1;
+ $second_interval = 1;
+ $extra_attrs = '';
+ $all_extra = null;
+ $hour_extra = null;
+ $minute_extra = null;
+ $second_extra = null;
+ $meridian_extra = null;
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ case 'time':
+ if (!is_array($_value) && $_value !== null) {
+ $time = smarty_make_timestamp($_value);
+ }
+ break;
+ case 'prefix':
+ case 'field_array':
+ case 'field_separator':
+ case 'option_separator':
+ case 'all_extra':
+ case 'hour_extra':
+ case 'minute_extra':
+ case 'second_extra':
+ case 'meridian_extra':
+ case 'all_empty':
+ case 'hour_empty':
+ case 'minute_empty':
+ case 'second_empty':
+ case 'meridian_empty':
+ case 'all_id':
+ case 'hour_id':
+ case 'minute_id':
+ case 'second_id':
+ case 'meridian_id':
+ case 'hour_format':
+ case 'hour_value_format':
+ case 'minute_format':
+ case 'minute_value_format':
+ case 'second_format':
+ case 'second_value_format':
+ $$_key = (string)$_value;
+ break;
+ case 'display_hours':
+ case 'display_minutes':
+ case 'display_seconds':
+ case 'display_meridian':
+ case 'use_24_hours':
+ $$_key = (bool)$_value;
+ break;
+ case 'minute_interval':
+ case 'second_interval':
+ case 'hour_size':
+ case 'minute_size':
+ case 'second_size':
+ case 'meridian_size':
+ $$_key = (int)$_value;
+ break;
+ default:
+ if (!is_array($_value)) {
+ $extra_attrs .= ' ' . $_key . '="' . smarty_function_escape_special_chars($_value) . '"';
+ } else {
+ trigger_error("html_select_date: extra attribute '{$_key}' cannot be an array", E_USER_NOTICE);
+ }
+ break;
+ }
+ }
+ if (isset($params['time']) && is_array($params['time'])) {
+ if (isset($params['time'][$prefix . 'Hour'])) {
+ // $_REQUEST[$field_array] given
+ foreach ([
+ 'H' => 'Hour',
+ 'i' => 'Minute',
+ 's' => 'Second'
+ ] as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName =
+ $params['time'][$prefix . $_elementName] ?? date($_elementKey);
+ }
+ $_meridian =
+ isset($params['time'][$prefix . 'Meridian']) ? (' ' . $params['time'][$prefix . 'Meridian']) :
+ '';
+ $time = strtotime($_hour . ':' . $_minute . ':' . $_second . $_meridian);
+ [$_hour, $_minute, $_second] = $time = explode('-', date('H-i-s', $time));
+ } elseif (isset($params['time'][$field_array][$prefix . 'Hour'])) {
+ // $_REQUEST given
+ foreach ([
+ 'H' => 'Hour',
+ 'i' => 'Minute',
+ 's' => 'Second'
+ ] as $_elementKey => $_elementName) {
+ $_variableName = '_' . strtolower($_elementName);
+ $$_variableName = $params['time'][$field_array][$prefix . $_elementName] ?? date($_elementKey);
+ }
+ $_meridian = isset($params['time'][$field_array][$prefix . 'Meridian']) ?
+ (' ' . $params['time'][$field_array][$prefix . 'Meridian']) : '';
+ $time = strtotime($_hour . ':' . $_minute . ':' . $_second . $_meridian);
+ [$_hour, $_minute, $_second] = $time = explode('-', date('H-i-s', $time));
+ } else {
+ // no date found, use NOW
+ [$_year, $_month, $_day] = $time = explode('-', date('Y-m-d'));
+ }
+ } elseif ($time === null) {
+ if (array_key_exists('time', $params)) {
+ $_hour = $_minute = $_second = $time = null;
+ } else {
+ [$_hour, $_minute, $_second] = $time = explode('-', date('H-i-s'));
+ }
+ } else {
+ [$_hour, $_minute, $_second] = $time = explode('-', date('H-i-s', $time));
+ }
+ // generate hour
+ if ($display_hours) {
+ $_html_hours = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Hour]') : ($prefix . 'Hour');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($hour_extra) {
+ $_extra .= ' ' . $hour_extra;
+ }
+ $_html_hours = '' . $option_separator;
+ if (isset($hour_empty) || isset($all_empty)) {
+ $_html_hours .= '' . (isset($hour_empty) ? $hour_empty : $all_empty) . ' ' .
+ $option_separator;
+ }
+ $start = $use_24_hours ? 0 : 1;
+ $end = $use_24_hours ? 23 : 12;
+ for ($i = $start; $i <= $end; $i++) {
+ $_val = sprintf('%02d', $i);
+ $_text = $hour_format === '%02d' ? $_val : sprintf($hour_format, $i);
+ $_value = $hour_value_format === '%02d' ? $_val : sprintf($hour_value_format, $i);
+ if (!$use_24_hours) {
+ $_hour12 = $_hour == 0 ? 12 : ($_hour <= 12 ? $_hour : $_hour - 12);
+ }
+ $selected = $_hour !== null ? ($use_24_hours ? $_hour == $_val : $_hour12 == $_val) : null;
+ $_html_hours .= '' .
+ $_text . ' ' . $option_separator;
+ }
+ $_html_hours .= ' ';
+ }
+ // generate minute
+ if ($display_minutes) {
+ $_html_minutes = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Minute]') : ($prefix . 'Minute');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($minute_extra) {
+ $_extra .= ' ' . $minute_extra;
+ }
+ $_html_minutes = '' . $option_separator;
+ if (isset($minute_empty) || isset($all_empty)) {
+ $_html_minutes .= '' . (isset($minute_empty) ? $minute_empty : $all_empty) . ' ' .
+ $option_separator;
+ }
+ $selected = $_minute !== null ? ($_minute - $_minute % $minute_interval) : null;
+ for ($i = 0; $i <= 59; $i += $minute_interval) {
+ $_val = sprintf('%02d', $i);
+ $_text = $minute_format === '%02d' ? $_val : sprintf($minute_format, $i);
+ $_value = $minute_value_format === '%02d' ? $_val : sprintf($minute_value_format, $i);
+ $_html_minutes .= '' . $_text . ' ' . $option_separator;
+ }
+ $_html_minutes .= ' ';
+ }
+ // generate second
+ if ($display_seconds) {
+ $_html_seconds = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Second]') : ($prefix . 'Second');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($second_extra) {
+ $_extra .= ' ' . $second_extra;
+ }
+ $_html_seconds = '' . $option_separator;
+ if (isset($second_empty) || isset($all_empty)) {
+ $_html_seconds .= '' . (isset($second_empty) ? $second_empty : $all_empty) . ' ' .
+ $option_separator;
+ }
+ $selected = $_second !== null ? ($_second - $_second % $second_interval) : null;
+ for ($i = 0; $i <= 59; $i += $second_interval) {
+ $_val = sprintf('%02d', $i);
+ $_text = $second_format === '%02d' ? $_val : sprintf($second_format, $i);
+ $_value = $second_value_format === '%02d' ? $_val : sprintf($second_value_format, $i);
+ $_html_seconds .= '' . $_text . ' ' . $option_separator;
+ }
+ $_html_seconds .= ' ';
+ }
+ // generate meridian
+ if ($display_meridian && !$use_24_hours) {
+ $_html_meridian = '';
+ $_extra = '';
+ $_name = $field_array ? ($field_array . '[' . $prefix . 'Meridian]') : ($prefix . 'Meridian');
+ if ($all_extra) {
+ $_extra .= ' ' . $all_extra;
+ }
+ if ($meridian_extra) {
+ $_extra .= ' ' . $meridian_extra;
+ }
+ $_html_meridian = '' . $option_separator;
+ if (isset($meridian_empty) || isset($all_empty)) {
+ $_html_meridian .= '' . (isset($meridian_empty) ? $meridian_empty : $all_empty) .
+ ' ' . $option_separator;
+ }
+ $_html_meridian .= ' 0 && $_hour < 12 ? ' selected="selected"' : '') .
+ '>AM ' . $option_separator . 'PM ' . $option_separator .
+ ' ';
+ }
+ $_html = '';
+ foreach ([
+ '_html_hours',
+ '_html_minutes',
+ '_html_seconds',
+ '_html_meridian'
+ ] as $k) {
+ if (isset($$k)) {
+ if ($_html) {
+ $_html .= $field_separator;
+ }
+ $_html .= $$k;
+ }
+ }
+ return $_html;
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlTable.php b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlTable.php
new file mode 100644
index 0000000..d5d1470
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/HtmlTable.php
@@ -0,0 +1,161 @@
+
+ * @version 1.1
+ *
+ * @author Monte Ohrt
+ * @author credit to Messju Mohr
+ */
+class HtmlTable extends Base {
+
+ public function handle($params, Template $template) {
+ $table_attr = 'border="1"';
+ $tr_attr = '';
+ $th_attr = '';
+ $td_attr = '';
+ $cols = $cols_count = 3;
+ $rows = 3;
+ $trailpad = ' ';
+ $vdir = 'down';
+ $hdir = 'right';
+ $inner = 'cols';
+ $caption = '';
+ $loop = null;
+ if (!isset($params['loop'])) {
+ trigger_error("html_table: missing 'loop' parameter", E_USER_WARNING);
+ return;
+ }
+ foreach ($params as $_key => $_value) {
+ switch ($_key) {
+ case 'loop':
+ $$_key = (array)$_value;
+ break;
+ case 'cols':
+ if (is_array($_value) && !empty($_value)) {
+ $cols = $_value;
+ $cols_count = count($_value);
+ } elseif (!is_numeric($_value) && is_string($_value) && !empty($_value)) {
+ $cols = explode(',', $_value);
+ $cols_count = count($cols);
+ } elseif (!empty($_value)) {
+ $cols_count = (int)$_value;
+ } else {
+ $cols_count = $cols;
+ }
+ break;
+ case 'rows':
+ $$_key = (int)$_value;
+ break;
+ case 'table_attr':
+ case 'trailpad':
+ case 'hdir':
+ case 'vdir':
+ case 'inner':
+ case 'caption':
+ $$_key = (string)$_value;
+ break;
+ case 'tr_attr':
+ case 'td_attr':
+ case 'th_attr':
+ $$_key = $_value;
+ break;
+ }
+ }
+ $loop_count = count($loop);
+ if (empty($params['rows'])) {
+ /* no rows specified */
+ $rows = ceil($loop_count / $cols_count);
+ } elseif (empty($params['cols'])) {
+ if (!empty($params['rows'])) {
+ /* no cols specified, but rows */
+ $cols_count = ceil($loop_count / $rows);
+ }
+ }
+ $output = "\n";
+ if (!empty($caption)) {
+ $output .= '' . $caption . " \n";
+ }
+ if (is_array($cols)) {
+ $cols = ($hdir === 'right') ? $cols : array_reverse($cols);
+ $output .= "\n";
+ for ($r = 0; $r < $cols_count; $r++) {
+ $output .= 'cycle('th', $th_attr, $r) . '>';
+ $output .= $cols[$r];
+ $output .= " \n";
+ }
+ $output .= " \n";
+ }
+ $output .= "\n";
+ for ($r = 0; $r < $rows; $r++) {
+ $output .= "cycle('tr', $tr_attr, $r) . ">\n";
+ $rx = ($vdir === 'down') ? $r * $cols_count : ($rows - 1 - $r) * $cols_count;
+ for ($c = 0; $c < $cols_count; $c++) {
+ $x = ($hdir === 'right') ? $rx + $c : $rx + $cols_count - 1 - $c;
+ if ($inner !== 'cols') {
+ /* shuffle x to loop over rows*/
+ $x = floor($x / $cols_count) + ($x % $cols_count) * $rows;
+ }
+ if ($x < $loop_count) {
+ $output .= "cycle('td', $td_attr, $c) . ">" . $loop[$x] . " \n";
+ } else {
+ $output .= "cycle('td', $td_attr, $c) . ">$trailpad \n";
+ }
+ }
+ $output .= " \n";
+ }
+ $output .= " \n";
+ $output .= "
\n";
+ return $output;
+ }
+
+ /**
+ * @param $name
+ * @param $var
+ * @param $no
+ *
+ * @return string
+ */
+ private function cycle($name, $var, $no) {
+ if (!is_array($var)) {
+ $ret = $var;
+ } else {
+ $ret = $var[$no % count($var)];
+ }
+ return ($ret) ? ' ' . $ret : '';
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/Mailto.php b/src/includes/smarty-5.4.1/src/FunctionHandler/Mailto.php
new file mode 100644
index 0000000..eb35c48
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/Mailto.php
@@ -0,0 +1,141 @@
+
+ * @author credits to Jason Sweat (added cc, bcc and subject functionality)
+ *
+ * @param array $params parameters
+ *
+ * @return string
+ */
+class Mailto extends Base {
+
+ public function handle($params, Template $template) {
+ static $_allowed_encoding = [
+ 'javascript' => true,
+ 'javascript_charcode' => true,
+ 'hex' => true,
+ 'none' => true
+ ];
+
+ $extra = '';
+ if (empty($params['address'])) {
+ trigger_error("mailto: missing 'address' parameter", E_USER_WARNING);
+ return;
+ } else {
+ $address = $params['address'];
+ }
+
+ $text = $address;
+
+ // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
+ // so, don't encode it.
+ $mail_parms = [];
+ foreach ($params as $var => $value) {
+ switch ($var) {
+ case 'cc':
+ case 'bcc':
+ case 'followupto':
+ if (!empty($value)) {
+ $mail_parms[] = $var . '=' . str_replace(['%40', '%2C'], ['@', ','], rawurlencode($value));
+ }
+ break;
+ case 'subject':
+ case 'newsgroups':
+ $mail_parms[] = $var . '=' . rawurlencode($value);
+ break;
+ case 'extra':
+ case 'text':
+ $$var = $value;
+ // no break
+ default:
+ }
+ }
+
+ if ($mail_parms) {
+ $address .= '?' . join('&', $mail_parms);
+ }
+ $encode = (empty($params['encode'])) ? 'none' : $params['encode'];
+ if (!isset($_allowed_encoding[$encode])) {
+ trigger_error(
+ "mailto: 'encode' parameter must be none, javascript, javascript_charcode or hex",
+ E_USER_WARNING
+ );
+ return;
+ }
+
+ $string = '' . htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, \Smarty\Smarty::$_CHARSET) . ' ';
+
+ if ($encode === 'javascript') {
+ $js_encode = '';
+ for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
+ $js_encode .= '%' . bin2hex($string[$x]);
+ }
+ return '';
+ } elseif ($encode === 'javascript_charcode') {
+ for ($x = 0, $_length = strlen($string); $x < $_length; $x++) {
+ $ord[] = ord($string[$x]);
+ }
+ return '';
+ } elseif ($encode === 'hex') {
+ preg_match('!^(.*)(\?.*)$!', $address, $match);
+ if (!empty($match[2])) {
+ trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.", E_USER_WARNING);
+ return;
+ }
+ $address_encode = '';
+ for ($x = 0, $_length = strlen($address); $x < $_length; $x++) {
+ if (preg_match('!\w!' . \Smarty\Smarty::$_UTF8_MODIFIER, $address[$x])) {
+ $address_encode .= '%' . bin2hex($address[$x]);
+ } else {
+ $address_encode .= $address[$x];
+ }
+ }
+ $text_encode = '';
+ for ($x = 0, $_length = strlen($text); $x < $_length; $x++) {
+ $text_encode .= '' . bin2hex($text[$x]) . ';';
+ }
+ $mailto = "mailto:";
+ return '' . $text_encode . ' ';
+ } else {
+ // no encoding
+ return $string;
+ }
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/FunctionHandler/Math.php b/src/includes/smarty-5.4.1/src/FunctionHandler/Math.php
new file mode 100644
index 0000000..23ef925
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/FunctionHandler/Math.php
@@ -0,0 +1,140 @@
+
+ *
+ * @param array $params parameters
+ * @param Template $template template object
+ *
+ * @return string|null
+ */
+class Math extends Base {
+
+ public function handle($params, Template $template) {
+ static $_allowed_funcs =
+ [
+ 'int' => true,
+ 'abs' => true,
+ 'ceil' => true,
+ 'acos' => true,
+ 'acosh' => true,
+ 'cos' => true,
+ 'cosh' => true,
+ 'deg2rad' => true,
+ 'rad2deg' => true,
+ 'exp' => true,
+ 'floor' => true,
+ 'log' => true,
+ 'log10' => true,
+ 'max' => true,
+ 'min' => true,
+ 'pi' => true,
+ 'pow' => true,
+ 'rand' => true,
+ 'round' => true,
+ 'asin' => true,
+ 'asinh' => true,
+ 'sin' => true,
+ 'sinh' => true,
+ 'sqrt' => true,
+ 'srand' => true,
+ 'atan' => true,
+ 'atanh' => true,
+ 'tan' => true,
+ 'tanh' => true
+ ];
+
+ // be sure equation parameter is present
+ if (empty($params['equation'])) {
+ trigger_error("math: missing equation parameter", E_USER_WARNING);
+ return;
+ }
+ $equation = $params['equation'];
+
+ // Remove whitespaces
+ $equation = preg_replace('/\s+/', '', $equation);
+
+ // Adapted from https://www.php.net/manual/en/function.eval.php#107377
+ $number = '-?(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
+ $functionsOrVars = '((?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*))';
+ $operators = '[,+\/*\^%-]'; // Allowed math operators
+ $regexp = '/^((' . $number . '|' . $functionsOrVars . '|(' . $functionsOrVars . '\s*\((?1)*\)|\((?1)*\)))(?:' . $operators . '(?1))?)+$/';
+
+ if (!preg_match($regexp, $equation)) {
+ trigger_error("math: illegal characters", E_USER_WARNING);
+ return;
+ }
+
+ // make sure parenthesis are balanced
+ if (substr_count($equation, '(') !== substr_count($equation, ')')) {
+ trigger_error("math: unbalanced parenthesis", E_USER_WARNING);
+ return;
+ }
+
+ // disallow backticks
+ if (strpos($equation, '`') !== false) {
+ trigger_error("math: backtick character not allowed in equation", E_USER_WARNING);
+ return;
+ }
+
+ // also disallow dollar signs
+ if (strpos($equation, '$') !== false) {
+ trigger_error("math: dollar signs not allowed in equation", E_USER_WARNING);
+ return;
+ }
+ foreach ($params as $key => $val) {
+ if ($key !== 'equation' && $key !== 'format' && $key !== 'assign') {
+ // make sure value is not empty
+ if (strlen($val) === 0) {
+ trigger_error("math: parameter '{$key}' is empty", E_USER_WARNING);
+ return;
+ }
+ if (!is_numeric($val)) {
+ trigger_error("math: parameter '{$key}' is not numeric", E_USER_WARNING);
+ return;
+ }
+ }
+ }
+ // match all vars in equation, make sure all are passed
+ preg_match_all('!(?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)!', $equation, $match);
+ foreach ($match[1] as $curr_var) {
+ if ($curr_var && !isset($params[$curr_var]) && !isset($_allowed_funcs[$curr_var])) {
+ trigger_error(
+ "math: function call '{$curr_var}' not allowed, or missing parameter '{$curr_var}'",
+ E_USER_WARNING
+ );
+ return;
+ }
+ }
+ foreach ($params as $key => $val) {
+ if ($key !== 'equation' && $key !== 'format' && $key !== 'assign') {
+ $equation = preg_replace("/\b$key\b/", " \$params['$key'] ", $equation);
+ }
+ }
+ $smarty_math_result = null;
+ eval("\$smarty_math_result = " . $equation . ";");
+
+ if (empty($params['format'])) {
+ if (empty($params['assign'])) {
+ return $smarty_math_result;
+ } else {
+ $template->assign($params['assign'], $smarty_math_result);
+ }
+ } else {
+ if (empty($params['assign'])) {
+ printf($params['format'], $smarty_math_result);
+ } else {
+ $template->assign($params['assign'], sprintf($params['format'], $smarty_math_result));
+ }
+ }
+ }
+}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_configfilelexer.php b/src/includes/smarty-5.4.1/src/Lexer/ConfigfileLexer.php
similarity index 57%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_configfilelexer.php
rename to src/includes/smarty-5.4.1/src/Lexer/ConfigfileLexer.php
index afb3efc..d592c82 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_configfilelexer.php
+++ b/src/includes/smarty-5.4.1/src/Lexer/ConfigfileLexer.php
@@ -1,111 +1,117 @@
'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE'
- );
+ public $state_name = array(1 => 'START', 2 => 'VALUE', 3 => 'NAKED_STRING_VALUE', 4 => 'COMMENT', 5 => 'SECTION', 6 => 'TRIPPLE');
+
+ /**
+ * storage for assembled token patterns
+ *
+ * @var string
+ */
+ private $yy_global_pattern1 = null;
+ private $yy_global_pattern2 = null;
+ private $yy_global_pattern3 = null;
+ private $yy_global_pattern4 = null;
+ private $yy_global_pattern5 = null;
+ private $yy_global_pattern6 = null;
/**
* token names
@@ -115,54 +121,19 @@ class Smarty_Internal_Configfilelexer
public $smarty_token_names = array( // Text for parser error messages
);
- /**
- * compiler object
- *
- * @var Smarty_Internal_Config_File_Compiler
- */
- private $compiler = null;
-
- /**
- * copy of config_booleanize
- *
- * @var bool
- */
- private $configBooleanize = false;
-
- /**
- * storage for assembled token patterns
- *
- * @var string
- */
- private $yy_global_pattern1 = null;
-
- private $yy_global_pattern2 = null;
-
- private $yy_global_pattern3 = null;
-
- private $yy_global_pattern4 = null;
-
- private $yy_global_pattern5 = null;
-
- private $yy_global_pattern6 = null;
-
- private $_yy_state = 1;
-
- private $_yy_stack = array();
-
/**
* constructor
*
* @param string $data template source
- * @param Smarty_Internal_Config_File_Compiler $compiler
+ * @param \Smarty\Compiler\Configfile $compiler
*/
- public function __construct($data, Smarty_Internal_Config_File_Compiler $compiler)
+ public function __construct($data, \Smarty\Compiler\Configfile $compiler)
{
$this->data = $data . "\n"; //now all lines are \n-terminated
$this->dataLength = strlen($data);
$this->counter = 0;
if (preg_match('/^\xEF\xBB\xBF/', $this->data, $match)) {
- $this->counter += strlen($match[ 0 ]);
+ $this->counter += strlen($match[0]);
}
$this->line = 1;
$this->compiler = $compiler;
@@ -170,10 +141,9 @@ class Smarty_Internal_Configfilelexer
$this->configBooleanize = $this->smarty->config_booleanize;
}
- public function replace($input)
- {
+ public function replace ($input) {
return $input;
- } // end function
+ }
public function PrintTrace()
{
@@ -181,6 +151,11 @@ class Smarty_Internal_Configfilelexer
$this->yyTracePrompt = ' ';
}
+
+
+ private $_yy_state = 1;
+ private $_yy_stack = array();
+
public function yylex()
{
return $this->{'yylex' . $this->_yy_state}();
@@ -189,85 +164,61 @@ class Smarty_Internal_Configfilelexer
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
- );
+ 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
- );
+ 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
- );
+ 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);
+ $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
- );
+ 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;
+ $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
- );
+ 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(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/isS");
+ $this->yy_global_pattern1 = $this->replace("/\G(#|;)|\G(\\[)|\G(\\])|\G(=)|\G([ \t\r]+)|\G(\n)|\G([0-9]*[a-zA-Z_]\\w*)|\G([\S\s])/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern1,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr(
- $this->data,
- $this->counter,
- 5
- ) . '... state START');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state START');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -285,89 +236,91 @@ class Smarty_Internal_Configfilelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
+ } } else {
throw new Exception('Unexpected input at line' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
- public function yy_r1_1()
- {
- $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART;
- $this->yypushstate(self::COMMENT);
- }
-
- public function yy_r1_2()
- {
- $this->token = Smarty_Internal_Configfileparser::TPC_OPENB;
- $this->yypushstate(self::SECTION);
- }
-
- public function yy_r1_3()
- {
- $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB;
- }
-
- public function yy_r1_4()
- {
- $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL;
- $this->yypushstate(self::VALUE);
} // end function
+
+ const START = 1;
+ public function yy_r1_1()
+ {
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_COMMENTSTART;
+ $this->yypushstate(self::COMMENT);
+ }
+ public function yy_r1_2()
+ {
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_OPENB;
+ $this->yypushstate(self::SECTION);
+ }
+ public function yy_r1_3()
+ {
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_CLOSEB;
+ }
+ public function yy_r1_4()
+ {
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_EQUAL;
+ $this->yypushstate(self::VALUE);
+ }
public function yy_r1_5()
{
- return false;
- }
+ return false;
+ }
public function yy_r1_6()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NEWLINE;
+ }
public function yy_r1_7()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_ID;
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_ID;
+ }
public function yy_r1_8()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_OTHER;
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_OTHER;
}
+
+
public function yylex2()
{
if (!isset($this->yy_global_pattern2)) {
- $this->yy_global_pattern2 =
- $this->replace("/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS");
+ $this->yy_global_pattern2 = $this->replace("/\G([ \t\r]+)|\G(\\d+\\.\\d+(?=[ \t\r]*[\n#;]))|\G(\\d+(?=[ \t\r]*[\n#;]))|\G(\"\"\")|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*'(?=[ \t\r]*[\n#;]))|\G(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"(?=[ \t\r]*[\n#;]))|\G([a-zA-Z]+(?=[ \t\r]*[\n#;]))|\G([^\n]+?(?=[ \t\r]*\n))|\G(\n)/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern2,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr(
- $this->data,
- $this->counter,
- 5
- ) . '... state VALUE');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state VALUE');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -385,80 +338,84 @@ class Smarty_Internal_Configfilelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
+ } } else {
throw new Exception('Unexpected input at line' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
+ } // end function
+
+
+ const VALUE = 2;
public function yy_r2_1()
{
- return false;
- }
+ return false;
+ }
public function yy_r2_2()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT;
- $this->yypopstate();
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_FLOAT;
+ $this->yypopstate();
+ }
public function yy_r2_3()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_INT;
- $this->yypopstate();
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_INT;
+ $this->yypopstate();
+ }
public function yy_r2_4()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES;
- $this->yypushstate(self::TRIPPLE);
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_TRIPPLE_QUOTES;
+ $this->yypushstate(self::TRIPPLE);
+ }
public function yy_r2_5()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING;
- $this->yypopstate();
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_SINGLE_QUOTED_STRING;
+ $this->yypopstate();
+ }
public function yy_r2_6()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING;
- $this->yypopstate();
- } // end function
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_DOUBLE_QUOTED_STRING;
+ $this->yypopstate();
+ }
public function yy_r2_7()
{
- if (!$this->configBooleanize ||
- !in_array(strtolower($this->value), array('true', 'false', 'on', 'off', 'yes', 'no'))) {
- $this->yypopstate();
- $this->yypushstate(self::NAKED_STRING_VALUE);
- return true; //reprocess in new state
- } else {
- $this->token = Smarty_Internal_Configfileparser::TPC_BOOL;
- $this->yypopstate();
- }
- }
+ if (!$this->configBooleanize || !in_array(strtolower($this->value), array('true', 'false', 'on', 'off', 'yes', 'no')) ) {
+ $this->yypopstate();
+ $this->yypushstate(self::NAKED_STRING_VALUE);
+ return true; //reprocess in new state
+ } else {
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_BOOL;
+ $this->yypopstate();
+ }
+ }
public function yy_r2_8()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
- $this->yypopstate();
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
+ $this->yypopstate();
+ }
public function yy_r2_9()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
- $this->value = '';
- $this->yypopstate();
- } // end function
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
+ $this->value = '';
+ $this->yypopstate();
+ }
+
+
public function yylex3()
{
@@ -468,23 +425,21 @@ class Smarty_Internal_Configfilelexer
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern3,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr(
- $this->data,
- $this->counter,
- 5
- ) . '... state NAKED_STRING_VALUE');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state NAKED_STRING_VALUE');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -502,26 +457,31 @@ class Smarty_Internal_Configfilelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
+ } } else {
throw new Exception('Unexpected input at line' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
+ } // end function
+
+
+ const NAKED_STRING_VALUE = 3;
public function yy_r3_1()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
- $this->yypopstate();
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
+ $this->yypopstate();
}
+
+
public function yylex4()
{
if (!isset($this->yy_global_pattern4)) {
@@ -530,23 +490,21 @@ class Smarty_Internal_Configfilelexer
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern4,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr(
- $this->data,
- $this->counter,
- 5
- ) . '... state COMMENT');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state COMMENT');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -564,36 +522,41 @@ class Smarty_Internal_Configfilelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
+ } } else {
throw new Exception('Unexpected input at line' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
- public function yy_r4_1()
- {
- return false;
- }
-
- public function yy_r4_2()
- {
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
} // end function
+
+ const COMMENT = 4;
+ public function yy_r4_1()
+ {
+
+ return false;
+ }
+ public function yy_r4_2()
+ {
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
+ }
public function yy_r4_3()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
- $this->yypopstate();
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NEWLINE;
+ $this->yypopstate();
}
+
+
public function yylex5()
{
if (!isset($this->yy_global_pattern5)) {
@@ -602,23 +565,21 @@ class Smarty_Internal_Configfilelexer
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern5,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr(
- $this->data,
- $this->counter,
- 5
- ) . '... state SECTION');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state SECTION');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -636,30 +597,34 @@ class Smarty_Internal_Configfilelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
+ } } else {
throw new Exception('Unexpected input at line' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
+ } // end function
+
+
+ const SECTION = 5;
public function yy_r5_1()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_DOT;
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_DOT;
+ }
public function yy_r5_2()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_SECTION;
- $this->yypopstate();
- } // end function
+
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_SECTION;
+ $this->yypopstate();
+ }
+
public function yylex6()
{
@@ -669,23 +634,21 @@ class Smarty_Internal_Configfilelexer
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern6, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern6,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr(
- $this->data,
- $this->counter,
- 5
- ) . '... state TRIPPLE');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state TRIPPLE');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -703,37 +666,42 @@ class Smarty_Internal_Configfilelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
+ } } else {
throw new Exception('Unexpected input at line' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
+ } // end function
+
+
+ const TRIPPLE = 6;
public function yy_r6_1()
{
- $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END;
- $this->yypopstate();
- $this->yypushstate(self::START);
- }
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_TRIPPLE_QUOTES_END;
+ $this->yypopstate();
+ $this->yypushstate(self::START);
+ }
public function yy_r6_2()
{
- $to = strlen($this->data);
- preg_match("/\"\"\"[ \t\r]*[\n#;]/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter);
- if (isset($match[ 0 ][ 1 ])) {
- $to = $match[ 0 ][ 1 ];
- } else {
- $this->compiler->trigger_config_file_error('missing or misspelled literal closing tag');
- }
- $this->value = substr($this->data, $this->counter, $to - $this->counter);
- $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT;
+
+ $to = strlen($this->data);
+ preg_match("/\"\"\"[ \t\r]*[\n#;]/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
+ if (isset($match[0][1])) {
+ $to = $match[0][1];
+ } else {
+ $this->compiler->trigger_config_file_error ('missing or misspelled literal closing tag');
+ }
+ $this->value = substr($this->data,$this->counter,$to-$this->counter);
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_TRIPPLE_TEXT;
}
+
+
}
diff --git a/src/includes/smarty-3.1.48/lexer/smarty_internal_configfilelexer.plex b/src/includes/smarty-5.4.1/src/Lexer/ConfigfileLexer.plex
similarity index 73%
rename from src/includes/smarty-3.1.48/lexer/smarty_internal_configfilelexer.plex
rename to src/includes/smarty-5.4.1/src/Lexer/ConfigfileLexer.plex
index 7a86fad..a895050 100644
--- a/src/includes/smarty-3.1.48/lexer/smarty_internal_configfilelexer.plex
+++ b/src/includes/smarty-5.4.1/src/Lexer/ConfigfileLexer.plex
@@ -1,6 +1,9 @@
data = $data . "\n"; //now all lines are \n-terminated
$this->dataLength = strlen($data);
@@ -179,31 +182,31 @@ naked_string = /[^\n]+?(?=[ \t\r]*\n)/
%statename START
commentstart {
- $this->token = Smarty_Internal_Configfileparser::TPC_COMMENTSTART;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_COMMENTSTART;
$this->yypushstate(self::COMMENT);
}
openB {
- $this->token = Smarty_Internal_Configfileparser::TPC_OPENB;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_OPENB;
$this->yypushstate(self::SECTION);
}
closeB {
- $this->token = Smarty_Internal_Configfileparser::TPC_CLOSEB;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_CLOSEB;
}
equal {
- $this->token = Smarty_Internal_Configfileparser::TPC_EQUAL;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_EQUAL;
$this->yypushstate(self::VALUE);
}
whitespace {
return false;
}
newline {
- $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NEWLINE;
}
id {
- $this->token = Smarty_Internal_Configfileparser::TPC_ID;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_ID;
}
text {
- $this->token = Smarty_Internal_Configfileparser::TPC_OTHER;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_OTHER;
}
*/
@@ -215,23 +218,23 @@ whitespace {
return false;
}
float {
- $this->token = Smarty_Internal_Configfileparser::TPC_FLOAT;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_FLOAT;
$this->yypopstate();
}
int {
- $this->token = Smarty_Internal_Configfileparser::TPC_INT;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_INT;
$this->yypopstate();
}
tripple_quotes {
- $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_TRIPPLE_QUOTES;
$this->yypushstate(self::TRIPPLE);
}
single_quoted_string {
- $this->token = Smarty_Internal_Configfileparser::TPC_SINGLE_QUOTED_STRING;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_SINGLE_QUOTED_STRING;
$this->yypopstate();
}
double_quoted_string {
- $this->token = Smarty_Internal_Configfileparser::TPC_DOUBLE_QUOTED_STRING;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_DOUBLE_QUOTED_STRING;
$this->yypopstate();
}
maybe_bool {
@@ -240,16 +243,16 @@ maybe_bool {
$this->yypushstate(self::NAKED_STRING_VALUE);
return true; //reprocess in new state
} else {
- $this->token = Smarty_Internal_Configfileparser::TPC_BOOL;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_BOOL;
$this->yypopstate();
}
}
naked_string {
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
$this->yypopstate();
}
newline {
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
$this->value = '';
$this->yypopstate();
}
@@ -260,7 +263,7 @@ newline {
%statename NAKED_STRING_VALUE
naked_string {
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
$this->yypopstate();
}
@@ -273,10 +276,10 @@ whitespace {
return false;
}
naked_string {
- $this->token = Smarty_Internal_Configfileparser::TPC_NAKED_STRING;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NAKED_STRING;
}
newline {
- $this->token = Smarty_Internal_Configfileparser::TPC_NEWLINE;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_NEWLINE;
$this->yypopstate();
}
@@ -286,10 +289,10 @@ newline {
%statename SECTION
dot {
- $this->token = Smarty_Internal_Configfileparser::TPC_DOT;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_DOT;
}
section {
- $this->token = Smarty_Internal_Configfileparser::TPC_SECTION;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_SECTION;
$this->yypopstate();
}
@@ -298,7 +301,7 @@ section {
%statename TRIPPLE
tripple_quotes_end {
- $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_QUOTES_END;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_TRIPPLE_QUOTES_END;
$this->yypopstate();
$this->yypushstate(self::START);
}
@@ -311,7 +314,7 @@ text {
$this->compiler->trigger_config_file_error ('missing or misspelled literal closing tag');
}
$this->value = substr($this->data,$this->counter,$to-$this->counter);
- $this->token = Smarty_Internal_Configfileparser::TPC_TRIPPLE_TEXT;
+ $this->token = \Smarty\Parser\ConfigfileParser::TPC_TRIPPLE_TEXT;
}
*/
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_templatelexer.php b/src/includes/smarty-5.4.1/src/Lexer/TemplateLexer.php
similarity index 53%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_templatelexer.php
rename to src/includes/smarty-5.4.1/src/Lexer/TemplateLexer.php
index 867a31d..2e7f330 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_templatelexer.php
+++ b/src/includes/smarty-5.4.1/src/Lexer/TemplateLexer.php
@@ -1,4 +1,7 @@
*/
-class Smarty_Internal_Templatelexer
+class TemplateLexer
{
- const TEXT = 1;
- const TAG = 2;
- const TAGBODY = 3;
- const LITERAL = 4;
- const DOUBLEQUOTEDSTRING = 5;
-
/**
* Source
*
@@ -73,14 +70,7 @@ class Smarty_Internal_Templatelexer
*/
public $taglineno;
- /**
- * php code type
- *
- * @var string
- */
- public $phpType = '';
-
- /**
+ /**
* state number
*
* @var int
@@ -97,7 +87,7 @@ class Smarty_Internal_Templatelexer
/**
* compiler object
*
- * @var Smarty_Internal_TemplateCompilerBase
+ * @var \Smarty\Compiler\Template
*/
public $compiler = null;
@@ -167,7 +157,6 @@ class Smarty_Internal_Templatelexer
'COMMENT' => 'comment',
'AS' => 'as',
'TO' => 'to',
- 'PHP' => '" '"<", "==" ... logical operator',
'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition',
'SCOND' => '"is even" ... if condition',
@@ -229,30 +218,26 @@ class Smarty_Internal_Templatelexer
*/
private $yy_global_literal = null;
- private $_yy_state = 1;
-
- private $_yy_stack = array();
-
/**
* constructor
*
* @param string $source template source
- * @param Smarty_Internal_TemplateCompilerBase $compiler
+ * @param \Smarty\Compiler\Template $compiler
*/
- public function __construct($source, Smarty_Internal_TemplateCompilerBase $compiler)
+ public function __construct($source, \Smarty\Compiler\Template $compiler)
{
$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 ]);
+ $this->counter += strlen($match[0]);
}
$this->line = 1;
- $this->smarty = $compiler->template->smarty;
+ $this->smarty = $compiler->getTemplate()->getSmarty();
$this->compiler = $compiler;
$this->compiler->initDelimiterPreg();
- $this->smarty_token_names[ 'LDEL' ] = $this->smarty->getLeftDelimiter();
- $this->smarty_token_names[ 'RDEL' ] = $this->smarty->getRightDelimiter();
+ $this->smarty_token_names['LDEL'] = $this->smarty->getLeftDelimiter();
+ $this->smarty_token_names['RDEL'] = $this->smarty->getRightDelimiter();
}
/**
@@ -265,17 +250,17 @@ class Smarty_Internal_Templatelexer
$this->yyTracePrompt = ' ';
}
- /**
+ /**
* replace placeholders with runtime preg code
*
* @param string $preg
*
* @return string
*/
- public function replace($preg)
- {
+ public function replace($preg)
+ {
return $this->compiler->replaceDelimiter($preg);
- }
+ }
/**
* check if current value is an autoliteral left delimiter
@@ -286,7 +271,11 @@ class Smarty_Internal_Templatelexer
{
return $this->smarty->getAutoLiteral() && isset($this->value[ $this->compiler->getLdelLength() ]) ?
strpos(" \n\t\r", $this->value[ $this->compiler->getLdelLength() ]) !== false : false;
- } // end function
+ }
+
+
+ private $_yy_state = 1;
+ private $_yy_stack = array();
public function yylex()
{
@@ -296,62 +285,60 @@ class Smarty_Internal_Templatelexer
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);
+ 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);
+ 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);
+ 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);
+ $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);
+ 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;
+ $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);
+ 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)SMARTYal[*])|\G((SMARTYldel)SMARTYalphp([ ].*?)?SMARTYrdel|(SMARTYldel)SMARTYal[\/]phpSMARTYrdel)|\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([<][?]((php\\s+|=)|\\s+)|[<][%]|[<][?]xml\\s+|[<]script\\s+language\\s*=\\s*[\"']?\\s*php\\s*[\"']?\\s*[>]|[?][>]|[%][>])|\G([\S\s])/isS");
+ $this->yy_global_pattern1 = $this->replace("/\G([{][}])|\G((SMARTYldel)SMARTYal[*])|\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([\S\s])/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern1,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr($this->data,
- $this->counter, 5) . '... state TEXT');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state TEXT');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -369,110 +356,102 @@ class Smarty_Internal_Templatelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
- throw new Exception('Unexpected input at line ' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ } } else {
+ throw new Exception('Unexpected input at line' . $this->line .
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
- public function yy_r1_1()
- {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
-
- public function yy_r1_2()
- {
- $to = $this->dataLength;
- preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/", $this->data, $match, PREG_OFFSET_CAPTURE,
- $this->counter);
- if (isset($match[ 0 ][ 1 ])) {
- $to = $match[ 0 ][ 1 ] + strlen($match[ 0 ][ 0 ]);
- } else {
- $this->compiler->trigger_template_error("missing or misspelled comment closing tag '{$this->smarty->getRightDelimiter()}'");
- }
- $this->value = substr($this->data, $this->counter, $to - $this->counter);
- return false;
- }
-
- public function yy_r1_4()
- {
- $this->compiler->getTagCompiler('private_php')->parsePhp($this);
- }
-
- public function yy_r1_8()
- {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
-
- public function yy_r1_10()
- {
- $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART;
- $this->yypushstate(self::LITERAL);
- }
-
- public function yy_r1_12()
- {
- $this->token = Smarty_Internal_Templateparser::TP_LITERALEND;
- $this->yypushstate(self::LITERAL);
} // end function
- public function yy_r1_14()
+
+ const TEXT = 1;
+ public function yy_r1_1()
{
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
+ public function yy_r1_2()
+ {
+
+ $to = $this->dataLength;
+ preg_match("/[*]{$this->compiler->getRdelPreg()}[\n]?/",$this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
+ if (isset($match[0][1])) {
+ $to = $match[0][1] + strlen($match[0][0]);
+ } else {
+ $this->compiler->trigger_template_error ("missing or misspelled comment closing tag '{$this->smarty->getRightDelimiter()}'");
+ }
+ $this->value = substr($this->data,$this->counter,$to-$this->counter);
+ return false;
+ }
+ public function yy_r1_4()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
+ public function yy_r1_6()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERALSTART;
+ $this->yypushstate(self::LITERAL);
+ }
+ public function yy_r1_8()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERALEND;
+ $this->yypushstate(self::LITERAL);
+ }
+ public function yy_r1_10()
+ {
+
$this->yypushstate(self::TAG);
return true;
- }
-
- public function yy_r1_16()
+ }
+ public function yy_r1_12()
{
- $this->compiler->getTagCompiler('private_php')->parsePhp($this);
- }
- public function yy_r1_19()
- {
- if (!isset($this->yy_global_text)) {
- $this->yy_global_text =
- $this->replace('/(SMARTYldel)SMARTYal|[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*[>]|[?][>]|[%][>]SMARTYliteral/isS');
- }
- $to = $this->dataLength;
- preg_match($this->yy_global_text, $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter);
- if (isset($match[ 0 ][ 1 ])) {
- $to = $match[ 0 ][ 1 ];
- }
- $this->value = substr($this->data, $this->counter, $to - $this->counter);
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
+ if (!isset($this->yy_global_text)) {
+ $this->yy_global_text = $this->replace('/(SMARTYldel)SMARTYal/isS');
+ }
+ $to = $this->dataLength;
+ preg_match($this->yy_global_text, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
+ if (isset($match[0][1])) {
+ $to = $match[0][1];
+ }
+ $this->value = substr($this->data,$this->counter,$to-$this->counter);
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
+
public function yylex2()
{
if (!isset($this->yy_global_pattern2)) {
- $this->yy_global_pattern2 =
- $this->replace("/\G((SMARTYldel)SMARTYal(if|elseif|else if|while)\\s+)|\G((SMARTYldel)SMARTYalfor\\s+)|\G((SMARTYldel)SMARTYalforeach(?![^\s]))|\G((SMARTYldel)SMARTYalsetfilter\\s+)|\G((SMARTYldel)SMARTYalmake_nocache\\s+)|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[$]smarty\\.block\\.(child|parent)\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/][0-9]*[a-zA-Z_]\\w*\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[$][0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal)/isS");
+ $this->yy_global_pattern2 = $this->replace("/\G((SMARTYldel)SMARTYal(if|elseif|else if|while)\\s+)|\G((SMARTYldel)SMARTYalfor\\s+)|\G((SMARTYldel)SMARTYalforeach(?![^\s]))|\G((SMARTYldel)SMARTYalsetfilter\\s+)|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[$]smarty\\.block\\.(child|parent)\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/][0-9]*[a-zA-Z_]\\w*\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[$][0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal)/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern2,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr($this->data,
- $this->counter, 5) . '... state TAG');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state TAG');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -490,127 +469,124 @@ class Smarty_Internal_Templatelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
- throw new Exception('Unexpected input at line ' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ } } else {
+ throw new Exception('Unexpected input at line' . $this->line .
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
+ } // end function
+
+
+ const TAG = 2;
public function yy_r2_1()
{
- $this->token = Smarty_Internal_Templateparser::TP_LDELIF;
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELIF;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
- }
-
+ }
public function yy_r2_4()
{
- $this->token = Smarty_Internal_Templateparser::TP_LDELFOR;
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELFOR;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
- }
-
+ }
public function yy_r2_6()
{
- $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH;
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELFOREACH;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
- }
-
+ }
public function yy_r2_8()
{
- $this->token = Smarty_Internal_Templateparser::TP_LDELSETFILTER;
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELSETFILTER;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
- }
-
+ }
public function yy_r2_10()
{
- $this->token = Smarty_Internal_Templateparser::TP_LDELMAKENOCACHE;
- $this->yybegin(self::TAGBODY);
- $this->taglineno = $this->line;
- }
- public function yy_r2_12()
- {
$this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SIMPLETAG;
$this->taglineno = $this->line;
- }
-
- public function yy_r2_15()
+ }
+ public function yy_r2_13()
{
- $this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILDPARENT;
- $this->taglineno = $this->line;
- }
+ $this->yypopstate();
+ $this->token = \Smarty\Parser\TemplateParser::TP_SMARTYBLOCKCHILDPARENT;
+ $this->taglineno = $this->line;
+ }
+ public function yy_r2_16()
+ {
+
+ $this->yypopstate();
+ $this->token = \Smarty\Parser\TemplateParser::TP_CLOSETAG;
+ $this->taglineno = $this->line;
+ }
public function yy_r2_18()
{
- $this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_CLOSETAG;
- $this->taglineno = $this->line;
- }
- public function yy_r2_20()
- {
- if ($this->_yy_stack[ count($this->_yy_stack) - 1 ] === self::TEXT) {
+ if ($this->_yy_stack[count($this->_yy_stack)-1] === self::TEXT) {
$this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_SIMPELOUTPUT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SIMPELOUTPUT;
$this->taglineno = $this->line;
} else {
$this->value = $this->smarty->getLeftDelimiter();
- $this->token = Smarty_Internal_Templateparser::TP_LDEL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDEL;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
- } // end function
+ }
+ public function yy_r2_21()
+ {
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELSLASH;
+ $this->yybegin(self::TAGBODY);
+ $this->taglineno = $this->line;
+ }
public function yy_r2_23()
{
- $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH;
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDEL;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
- }
-
- public function yy_r2_25()
- {
- $this->token = Smarty_Internal_Templateparser::TP_LDEL;
- $this->yybegin(self::TAGBODY);
- $this->taglineno = $this->line;
- }
+ }
+
public function yylex3()
{
if (!isset($this->yy_global_pattern3)) {
- $this->yy_global_pattern3 =
- $this->replace("/\G(\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*([!=][=]{1,2}|[<][=>]?|[>][=]?|[&|]{2})\\s*)|\G(\\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even|div)\\s+by\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G([!]\\s*|not\\s+)|\G([(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\\s*)|\G(\\s*[(]\\s*)|\G(\\s*[)])|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*[-][>]\\s*)|\G(\\s*[=][>]\\s*)|\G(\\s*[=]\\s*)|\G(([+]|[-]){2})|\G(\\s*([+]|[-])\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G([@])|\G(array\\s*[(]\\s*)|\G([#])|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*[=]\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G([`])|\G([|][@]?)|\G([.])|\G(\\s*[,]\\s*)|\G(\\s*[;]\\s*)|\G([:]{2})|\G(\\s*[:]\\s*)|\G(\\s*[?]\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G([\S\s])/isS");
+ $this->yy_global_pattern3 = $this->replace("/\G(\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(\\s+is\\s+(not\\s+)?in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*([!=][=]{1,2}|[<][=>]?|[>][=]?|[&|]{2})\\s*)|\G(\\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even|div)\\s+by\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G([!]\\s*|not\\s+)|\G([(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\\s*)|\G(\\s*[(]\\s*)|\G(\\s*[)])|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*[-][>]\\s*)|\G(\\s*[=][>]\\s*)|\G(\\s*[=]\\s*)|\G(([+]|[-]){2})|\G(\\s*([+]|[-])\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G([@])|\G(array\\s*[(]\\s*)|\G([#])|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*[=]\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G([`])|\G([|][@]?)|\G([.])|\G(\\s*[,]\\s*)|\G(\\s*[;]\\s*)|\G([:]{2})|\G(\\s*[:]\\s*)|\G(\\s*[?]\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G([\S\s])/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern3,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr($this->data,
- $this->counter, 5) . '... state TAGBODY');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state TAGBODY');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -628,281 +604,285 @@ class Smarty_Internal_Templatelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
- throw new Exception('Unexpected input at line ' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ } } else {
+ throw new Exception('Unexpected input at line' . $this->line .
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
- public function yy_r3_1()
- {
- $this->token = Smarty_Internal_Templateparser::TP_RDEL;
- $this->yypopstate();
- }
-
- public function yy_r3_2()
- {
- $this->yypushstate(self::TAG);
- return true;
- }
-
- public function yy_r3_4()
- {
- $this->token = Smarty_Internal_Templateparser::TP_QUOTE;
- $this->yypushstate(self::DOUBLEQUOTEDSTRING);
- $this->compiler->enterDoubleQuote();
- }
-
- public function yy_r3_5()
- {
- $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING;
- }
-
- public function yy_r3_6()
- {
- $this->token = Smarty_Internal_Templateparser::TP_DOLLARID;
- }
-
- public function yy_r3_7()
- {
- $this->token = Smarty_Internal_Templateparser::TP_DOLLAR;
- }
-
- public function yy_r3_8()
- {
- $this->token = Smarty_Internal_Templateparser::TP_ISIN;
- }
-
- public function yy_r3_9()
- {
- $this->token = Smarty_Internal_Templateparser::TP_AS;
- }
-
- public function yy_r3_10()
- {
- $this->token = Smarty_Internal_Templateparser::TP_TO;
- }
-
- public function yy_r3_11()
- {
- $this->token = Smarty_Internal_Templateparser::TP_STEP;
- }
-
- public function yy_r3_12()
- {
- $this->token = Smarty_Internal_Templateparser::TP_INSTANCEOF;
- }
-
- public function yy_r3_13()
- {
- $this->token = Smarty_Internal_Templateparser::TP_LOGOP;
- }
-
- public function yy_r3_15()
- {
- $this->token = Smarty_Internal_Templateparser::TP_SLOGOP;
- }
-
- public function yy_r3_17()
- {
- $this->token = Smarty_Internal_Templateparser::TP_TLOGOP;
- }
-
- public function yy_r3_20()
- {
- $this->token = Smarty_Internal_Templateparser::TP_SINGLECOND;
- }
-
- public function yy_r3_23()
- {
- $this->token = Smarty_Internal_Templateparser::TP_NOT;
- }
-
- public function yy_r3_24()
- {
- $this->token = Smarty_Internal_Templateparser::TP_TYPECAST;
- }
-
- public function yy_r3_28()
- {
- $this->token = Smarty_Internal_Templateparser::TP_OPENP;
- }
-
- public function yy_r3_29()
- {
- $this->token = Smarty_Internal_Templateparser::TP_CLOSEP;
- }
-
- public function yy_r3_30()
- {
- $this->token = Smarty_Internal_Templateparser::TP_OPENB;
- }
-
- public function yy_r3_31()
- {
- $this->token = Smarty_Internal_Templateparser::TP_CLOSEB;
- }
-
- public function yy_r3_32()
- {
- $this->token = Smarty_Internal_Templateparser::TP_PTR;
- }
-
- public function yy_r3_33()
- {
- $this->token = Smarty_Internal_Templateparser::TP_APTR;
- }
-
- public function yy_r3_34()
- {
- $this->token = Smarty_Internal_Templateparser::TP_EQUAL;
- }
-
- public function yy_r3_35()
- {
- $this->token = Smarty_Internal_Templateparser::TP_INCDEC;
- }
-
- public function yy_r3_37()
- {
- $this->token = Smarty_Internal_Templateparser::TP_UNIMATH;
- }
-
- public function yy_r3_39()
- {
- $this->token = Smarty_Internal_Templateparser::TP_MATH;
- }
-
- public function yy_r3_41()
- {
- $this->token = Smarty_Internal_Templateparser::TP_AT;
- }
-
- public function yy_r3_42()
- {
- $this->token = Smarty_Internal_Templateparser::TP_ARRAYOPEN;
- }
-
- public function yy_r3_43()
- {
- $this->token = Smarty_Internal_Templateparser::TP_HATCH;
- }
-
- public function yy_r3_44()
- {
- // resolve conflicts with shorttag and right_delimiter starting with '='
- if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->compiler->getRdelLength()) ===
- $this->smarty->getRightDelimiter()) {
- preg_match('/\s+/', $this->value, $match);
- $this->value = $match[ 0 ];
- $this->token = Smarty_Internal_Templateparser::TP_SPACE;
- } else {
- $this->token = Smarty_Internal_Templateparser::TP_ATTR;
- }
- }
-
- public function yy_r3_45()
- {
- $this->token = Smarty_Internal_Templateparser::TP_NAMESPACE;
- }
-
- public function yy_r3_48()
- {
- $this->token = Smarty_Internal_Templateparser::TP_ID;
- }
-
- public function yy_r3_49()
- {
- $this->token = Smarty_Internal_Templateparser::TP_INTEGER;
- }
-
- public function yy_r3_50()
- {
- $this->token = Smarty_Internal_Templateparser::TP_BACKTICK;
- $this->yypopstate();
- }
-
- public function yy_r3_51()
- {
- $this->token = Smarty_Internal_Templateparser::TP_VERT;
- }
-
- public function yy_r3_52()
- {
- $this->token = Smarty_Internal_Templateparser::TP_DOT;
- }
-
- public function yy_r3_53()
- {
- $this->token = Smarty_Internal_Templateparser::TP_COMMA;
- }
-
- public function yy_r3_54()
- {
- $this->token = Smarty_Internal_Templateparser::TP_SEMICOLON;
- }
-
- public function yy_r3_55()
- {
- $this->token = Smarty_Internal_Templateparser::TP_DOUBLECOLON;
- }
-
- public function yy_r3_56()
- {
- $this->token = Smarty_Internal_Templateparser::TP_COLON;
- }
-
- public function yy_r3_57()
- {
- $this->token = Smarty_Internal_Templateparser::TP_QMARK;
- }
-
- public function yy_r3_58()
- {
- $this->token = Smarty_Internal_Templateparser::TP_HEX;
- }
-
- public function yy_r3_59()
- {
- $this->token = Smarty_Internal_Templateparser::TP_SPACE;
} // end function
+
+ const TAGBODY = 3;
+ public function yy_r3_1()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_RDEL;
+ $this->yypopstate();
+ }
+ public function yy_r3_2()
+ {
+
+ $this->yypushstate(self::TAG);
+ return true;
+ }
+ public function yy_r3_4()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_QUOTE;
+ $this->yypushstate(self::DOUBLEQUOTEDSTRING);
+ $this->compiler->enterDoubleQuote();
+ }
+ public function yy_r3_5()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_SINGLEQUOTESTRING;
+ }
+ public function yy_r3_6()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOLLARID;
+ }
+ public function yy_r3_7()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOLLAR;
+ }
+ public function yy_r3_8()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_ISIN;
+ }
+ public function yy_r3_10()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_AS;
+ }
+ public function yy_r3_11()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_TO;
+ }
+ public function yy_r3_12()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_STEP;
+ }
+ public function yy_r3_13()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_INSTANCEOF;
+ }
+ public function yy_r3_14()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LOGOP;
+ }
+ public function yy_r3_16()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_SLOGOP;
+ }
+ public function yy_r3_18()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_TLOGOP;
+ }
+ public function yy_r3_21()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_SINGLECOND;
+ }
+ public function yy_r3_24()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_NOT;
+ }
+ public function yy_r3_25()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_TYPECAST;
+ }
+ public function yy_r3_29()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_OPENP;
+ }
+ public function yy_r3_30()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_CLOSEP;
+ }
+ public function yy_r3_31()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_OPENB;
+ }
+ public function yy_r3_32()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_CLOSEB;
+ }
+ public function yy_r3_33()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_PTR;
+ }
+ public function yy_r3_34()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_APTR;
+ }
+ public function yy_r3_35()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_EQUAL;
+ }
+ public function yy_r3_36()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_INCDEC;
+ }
+ public function yy_r3_38()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_UNIMATH;
+ }
+ public function yy_r3_40()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_MATH;
+ }
+ public function yy_r3_42()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_AT;
+ }
+ public function yy_r3_43()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_ARRAYOPEN;
+ }
+ public function yy_r3_44()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_HATCH;
+ }
+ public function yy_r3_45()
+ {
+
+ // resolve conflicts with shorttag and right_delimiter starting with '='
+ if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->compiler->getRdelLength()) === $this->smarty->getRightDelimiter()) {
+ preg_match('/\s+/',$this->value,$match);
+ $this->value = $match[0];
+ $this->token = \Smarty\Parser\TemplateParser::TP_SPACE;
+ } else {
+ $this->token = \Smarty\Parser\TemplateParser::TP_ATTR;
+ }
+ }
+ public function yy_r3_46()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_NAMESPACE;
+ }
+ public function yy_r3_49()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_ID;
+ }
+ public function yy_r3_50()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_INTEGER;
+ }
+ public function yy_r3_51()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_BACKTICK;
+ $this->yypopstate();
+ }
+ public function yy_r3_52()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_VERT;
+ }
+ public function yy_r3_53()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOT;
+ }
+ public function yy_r3_54()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_COMMA;
+ }
+ public function yy_r3_55()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_SEMICOLON;
+ }
+ public function yy_r3_56()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOUBLECOLON;
+ }
+ public function yy_r3_57()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_COLON;
+ }
+ public function yy_r3_58()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_QMARK;
+ }
+ public function yy_r3_59()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_HEX;
+ }
public function yy_r3_60()
{
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_SPACE;
+ }
+ public function yy_r3_61()
+ {
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
+
+
+
public function yylex4()
{
if (!isset($this->yy_global_pattern4)) {
- $this->yy_global_pattern4 =
- $this->replace("/\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G([\S\s])/isS");
+ $this->yy_global_pattern4 = $this->replace("/\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G([\S\s])/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern4,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr($this->data,
- $this->counter, 5) . '... state LITERAL');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state LITERAL');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -920,76 +900,80 @@ class Smarty_Internal_Templatelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
- throw new Exception('Unexpected input at line ' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ } } else {
+ throw new Exception('Unexpected input at line' . $this->line .
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
- public function yy_r4_1()
- {
- $this->literal_cnt++;
- $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
- }
-
- public function yy_r4_3()
- {
- if ($this->literal_cnt) {
- $this->literal_cnt--;
- $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
- } else {
- $this->token = Smarty_Internal_Templateparser::TP_LITERALEND;
- $this->yypopstate();
- }
- }
-
- public function yy_r4_5()
- {
- if (!isset($this->yy_global_literal)) {
- $this->yy_global_literal = $this->replace('/(SMARTYldel)SMARTYal[\/]?literalSMARTYrdel/isS');
- }
- $to = $this->dataLength;
- preg_match($this->yy_global_literal, $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter);
- if (isset($match[ 0 ][ 1 ])) {
- $to = $match[ 0 ][ 1 ];
- } else {
- $this->compiler->trigger_template_error("missing or misspelled literal closing tag");
- }
- $this->value = substr($this->data, $this->counter, $to - $this->counter);
- $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
} // end function
+
+ const LITERAL = 4;
+ public function yy_r4_1()
+ {
+
+ $this->literal_cnt++;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERAL;
+ }
+ public function yy_r4_3()
+ {
+
+ if ($this->literal_cnt) {
+ $this->literal_cnt--;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERAL;
+ } else {
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERALEND;
+ $this->yypopstate();
+ }
+ }
+ public function yy_r4_5()
+ {
+
+ if (!isset($this->yy_global_literal)) {
+ $this->yy_global_literal = $this->replace('/(SMARTYldel)SMARTYal[\/]?literalSMARTYrdel/isS');
+ }
+ $to = $this->dataLength;
+ preg_match($this->yy_global_literal, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
+ if (isset($match[0][1])) {
+ $to = $match[0][1];
+ } else {
+ $this->compiler->trigger_template_error ("missing or misspelled literal closing tag");
+ }
+ $this->value = substr($this->data,$this->counter,$to-$this->counter);
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERAL;
+ }
+
+
public function yylex5()
{
if (!isset($this->yy_global_pattern5)) {
- $this->yy_global_pattern5 =
- $this->replace("/\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G([`][$])|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(([^\"\\\\]*?)((?:\\\\.[^\"\\\\]*?)*?)(?=((SMARTYldel)SMARTYal|\\$|`\\$|\"SMARTYliteral)))|\G([\S\s])/isS");
+ $this->yy_global_pattern5 = $this->replace("/\G((SMARTYldel)SMARTYautoliteral\\s+SMARTYliteral)|\G((SMARTYldel)SMARTYalliteral\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/]literal\\s*SMARTYrdel)|\G((SMARTYldel)SMARTYal[\/])|\G((SMARTYldel)SMARTYal[0-9]*[a-zA-Z_]\\w*)|\G((SMARTYldel)SMARTYal)|\G([\"])|\G([`][$])|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(([^\"\\\\]*?)((?:\\\\.[^\"\\\\]*?)*?)(?=((SMARTYldel)SMARTYal|\\$|`\\$|\"SMARTYliteral)))|\G([\S\s])/isS");
}
if (!isset($this->dataLength)) {
$this->dataLength = strlen($this->data);
}
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
+
do {
- if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, 0, $this->counter)) {
- if (!isset($yymatches[ 0 ][ 1 ])) {
- $yymatches = preg_grep("/(.|\s)+/", $yymatches);
+ if (preg_match($this->yy_global_pattern5,$this->data, $yymatches, 0, $this->counter)) {
+ if (!isset($yymatches[ 0 ][1])) {
+ $yymatches = preg_grep("/(.|\s)+/", $yymatches);
} else {
$yymatches = array_filter($yymatches);
}
if (empty($yymatches)) {
throw new Exception('Error: lexing failed because a rule matched' .
- ' an empty string. Input "' . substr($this->data,
- $this->counter, 5) . '... state DOUBLEQUOTEDSTRING');
+ ' an empty string. Input "' . substr($this->data,
+ $this->counter, 5) . '... state DOUBLEQUOTEDSTRING');
}
next($yymatches); // skip global match
$this->token = key($yymatches); // token number
@@ -1007,89 +991,93 @@ class Smarty_Internal_Templatelexer
} elseif ($r === false) {
$this->counter += strlen($this->value);
$this->line += substr_count($this->value, "\n");
- if ($this->counter >= $this->dataLength) {
+ if ($this->counter >= $this->dataLength) {
return false; // end of input
}
// skip this token
continue;
- }
- } else {
- throw new Exception('Unexpected input at line ' . $this->line .
- ': ' . $this->data[ $this->counter ]);
+ } } else {
+ throw new Exception('Unexpected input at line' . $this->line .
+ ': ' . $this->data[$this->counter]);
}
break;
} while (true);
- }
+ } // end function
+
+
+ const DOUBLEQUOTEDSTRING = 5;
public function yy_r5_1()
{
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
public function yy_r5_3()
{
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
public function yy_r5_5()
{
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
public function yy_r5_7()
{
+
$this->yypushstate(self::TAG);
return true;
- }
-
+ }
public function yy_r5_9()
{
+
$this->yypushstate(self::TAG);
return true;
- }
-
+ }
public function yy_r5_11()
{
- $this->token = Smarty_Internal_Templateparser::TP_LDEL;
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDEL;
$this->taglineno = $this->line;
$this->yypushstate(self::TAGBODY);
- }
-
+ }
public function yy_r5_13()
{
- $this->token = Smarty_Internal_Templateparser::TP_QUOTE;
- $this->yypopstate();
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_QUOTE;
+ $this->yypopstate();
+ }
public function yy_r5_14()
{
- $this->token = Smarty_Internal_Templateparser::TP_BACKTICK;
- $this->value = substr($this->value, 0, -1);
+
+ $this->token = \Smarty\Parser\TemplateParser::TP_BACKTICK;
+ $this->value = substr($this->value,0,-1);
$this->yypushstate(self::TAGBODY);
$this->taglineno = $this->line;
- }
-
+ }
public function yy_r5_15()
{
- $this->token = Smarty_Internal_Templateparser::TP_DOLLARID;
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOLLARID;
+ }
public function yy_r5_16()
{
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
public function yy_r5_17()
{
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
public function yy_r5_22()
{
- $to = $this->dataLength;
- $this->value = substr($this->data, $this->counter, $to - $this->counter);
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
- }
-}
-
+ $to = $this->dataLength;
+ $this->value = substr($this->data,$this->counter,$to-$this->counter);
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
+ }
+
+ }
+
+
\ No newline at end of file
diff --git a/src/includes/smarty-3.1.48/lexer/smarty_internal_templatelexer.plex b/src/includes/smarty-5.4.1/src/Lexer/TemplateLexer.plex
similarity index 70%
rename from src/includes/smarty-3.1.48/lexer/smarty_internal_templatelexer.plex
rename to src/includes/smarty-5.4.1/src/Lexer/TemplateLexer.plex
index ac12502..282a99c 100644
--- a/src/includes/smarty-3.1.48/lexer/smarty_internal_templatelexer.plex
+++ b/src/includes/smarty-5.4.1/src/Lexer/TemplateLexer.plex
@@ -1,4 +1,7 @@
*/
-class Smarty_Internal_Templatelexer
+class TemplateLexer
{
/**
* Source
@@ -67,13 +70,6 @@ class Smarty_Internal_Templatelexer
*/
public $taglineno;
- /**
- * php code type
- *
- * @var string
- */
- public $phpType = '';
-
/**
* state number
*
@@ -91,7 +87,7 @@ class Smarty_Internal_Templatelexer
/**
* compiler object
*
- * @var Smarty_Internal_TemplateCompilerBase
+ * @var \Smarty\Compiler\Template
*/
public $compiler = null;
@@ -161,7 +157,6 @@ class Smarty_Internal_Templatelexer
'COMMENT' => 'comment',
'AS' => 'as',
'TO' => 'to',
- 'PHP' => '" '"<", "==" ... logical operator',
'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition',
'SCOND' => '"is even" ... if condition',
@@ -227,9 +222,9 @@ class Smarty_Internal_Templatelexer
* constructor
*
* @param string $source template source
- * @param Smarty_Internal_TemplateCompilerBase $compiler
+ * @param \Smarty\Compiler\Template $compiler
*/
- public function __construct($source, Smarty_Internal_TemplateCompilerBase $compiler)
+ public function __construct($source, \Smarty\Compiler\Template $compiler)
{
$this->data = $source;
$this->dataLength = strlen($this->data);
@@ -238,7 +233,7 @@ class Smarty_Internal_Templatelexer
$this->counter += strlen($match[0]);
}
$this->line = 1;
- $this->smarty = $compiler->template->smarty;
+ $this->smarty = $compiler->getTemplate()->getSmarty();
$this->compiler = $compiler;
$this->compiler->initDelimiterPreg();
$this->smarty_token_names['LDEL'] = $this->smarty->getLeftDelimiter();
@@ -289,8 +284,6 @@ class Smarty_Internal_Templatelexer
textdoublequoted = ~([^"\\]*?)((?:\\.[^"\\]*?)*?)(?=((SMARTYldel)SMARTYal|\$|`\$|"SMARTYliteral))~
namespace = ~([0-9]*[a-zA-Z_]\w*)?(\\[0-9]*[a-zA-Z_]\w*)+~
emptyjava = ~[{][}]~
- phptag = ~(SMARTYldel)SMARTYalphp([ ].*?)?SMARTYrdel|(SMARTYldel)SMARTYal[/]phpSMARTYrdel~
- phpstart = ~[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["']?\s*php\s*["']?\s*[>]|[?][>]|[%][>]~
slash = ~[/]~
ldel = ~(SMARTYldel)SMARTYal~
rdel = ~\s*SMARTYrdel~
@@ -331,13 +324,12 @@ class Smarty_Internal_Templatelexer
slop = ~\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\s+~
tlop = ~\s+is\s+(not\s+)?(odd|even|div)\s+by\s+~
scond = ~\s+is\s+(not\s+)?(odd|even)~
- isin = ~\s+is\s+in\s+~
+ isin = ~\s+is\s+(not\s+)?in\s+~
as = ~\s+as\s+~
to = ~\s+to\s+~
step = ~\s+step\s+~
if = ~(if|elseif|else if|while)\s+~
for = ~for\s+~
- makenocache = ~make_nocache\s+~
array = ~array~
foreach = ~foreach(?![^\s])~
setfilter = ~setfilter\s+~
@@ -349,7 +341,7 @@ class Smarty_Internal_Templatelexer
/*!lex2php
%statename TEXT
emptyjava {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
comment {
$to = $this->dataLength;
@@ -362,30 +354,24 @@ class Smarty_Internal_Templatelexer
$this->value = substr($this->data,$this->counter,$to-$this->counter);
return false;
}
- phptag {
- $this->compiler->getTagCompiler('private_php')->parsePhp($this);
- }
userliteral {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
ldel literal rdel {
- $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERALSTART;
$this->yypushstate(self::LITERAL);
}
ldel slash literal rdel {
- $this->token = Smarty_Internal_Templateparser::TP_LITERALEND;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERALEND;
$this->yypushstate(self::LITERAL);
}
ldel {
$this->yypushstate(self::TAG);
return true;
}
- phpstart {
- $this->compiler->getTagCompiler('private_php')->parsePhp($this);
- }
char {
if (!isset($this->yy_global_text)) {
- $this->yy_global_text = $this->replace('/(SMARTYldel)SMARTYal|[<][?]((php\s+|=)|\s+)|[<][%]|[<][?]xml\s+|[<]script\s+language\s*=\s*["\']?\s*php\s*["\']?\s*[>]|[?][>]|[%][>]SMARTYliteral/isS');
+ $this->yy_global_text = $this->replace('/(SMARTYldel)SMARTYal/isS');
}
$to = $this->dataLength;
preg_match($this->yy_global_text, $this->data,$match,PREG_OFFSET_CAPTURE,$this->counter);
@@ -393,70 +379,65 @@ class Smarty_Internal_Templatelexer
$to = $match[0][1];
}
$this->value = substr($this->data,$this->counter,$to-$this->counter);
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
*/
/*!lex2php
%statename TAG
ldel if {
- $this->token = Smarty_Internal_Templateparser::TP_LDELIF;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELIF;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
ldel for {
- $this->token = Smarty_Internal_Templateparser::TP_LDELFOR;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELFOR;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
ldel foreach {
- $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELFOREACH;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
ldel setfilter {
- $this->token = Smarty_Internal_Templateparser::TP_LDELSETFILTER;
- $this->yybegin(self::TAGBODY);
- $this->taglineno = $this->line;
- }
- ldel makenocache {
- $this->token = Smarty_Internal_Templateparser::TP_LDELMAKENOCACHE;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELSETFILTER;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
ldel id nocacherdel {
$this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SIMPLETAG;
$this->taglineno = $this->line;
}
ldel smartyblockchildparent rdel {
$this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILDPARENT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SMARTYBLOCKCHILDPARENT;
$this->taglineno = $this->line;
}
ldel slash id rdel {
$this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_CLOSETAG;
+ $this->token = \Smarty\Parser\TemplateParser::TP_CLOSETAG;
$this->taglineno = $this->line;
}
ldel dollar id nocacherdel {
if ($this->_yy_stack[count($this->_yy_stack)-1] === self::TEXT) {
$this->yypopstate();
- $this->token = Smarty_Internal_Templateparser::TP_SIMPELOUTPUT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SIMPELOUTPUT;
$this->taglineno = $this->line;
} else {
$this->value = $this->smarty->getLeftDelimiter();
- $this->token = Smarty_Internal_Templateparser::TP_LDEL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDEL;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
}
ldel slash {
- $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDELSLASH;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
ldel {
- $this->token = Smarty_Internal_Templateparser::TP_LDEL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDEL;
$this->yybegin(self::TAGBODY);
$this->taglineno = $this->line;
}
@@ -464,7 +445,7 @@ class Smarty_Internal_Templatelexer
/*!lex2php
%statename TAGBODY
rdel {
- $this->token = Smarty_Internal_Templateparser::TP_RDEL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_RDEL;
$this->yypopstate();
}
ldel {
@@ -472,143 +453,143 @@ class Smarty_Internal_Templatelexer
return true;
}
double_quote {
- $this->token = Smarty_Internal_Templateparser::TP_QUOTE;
+ $this->token = \Smarty\Parser\TemplateParser::TP_QUOTE;
$this->yypushstate(self::DOUBLEQUOTEDSTRING);
$this->compiler->enterDoubleQuote();
}
singlequotestring {
- $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SINGLEQUOTESTRING;
}
dollar id {
- $this->token = Smarty_Internal_Templateparser::TP_DOLLARID;
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOLLARID;
}
dollar {
- $this->token = Smarty_Internal_Templateparser::TP_DOLLAR;
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOLLAR;
}
isin {
- $this->token = Smarty_Internal_Templateparser::TP_ISIN;
+ $this->token = \Smarty\Parser\TemplateParser::TP_ISIN;
}
as {
- $this->token = Smarty_Internal_Templateparser::TP_AS;
+ $this->token = \Smarty\Parser\TemplateParser::TP_AS;
}
to {
- $this->token = Smarty_Internal_Templateparser::TP_TO;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TO;
}
step {
- $this->token = Smarty_Internal_Templateparser::TP_STEP;
+ $this->token = \Smarty\Parser\TemplateParser::TP_STEP;
}
instanceof {
- $this->token = Smarty_Internal_Templateparser::TP_INSTANCEOF;
+ $this->token = \Smarty\Parser\TemplateParser::TP_INSTANCEOF;
}
lop {
- $this->token = Smarty_Internal_Templateparser::TP_LOGOP;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LOGOP;
}
slop {
- $this->token = Smarty_Internal_Templateparser::TP_SLOGOP;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SLOGOP;
}
tlop {
- $this->token = Smarty_Internal_Templateparser::TP_TLOGOP;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TLOGOP;
}
scond {
- $this->token = Smarty_Internal_Templateparser::TP_SINGLECOND;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SINGLECOND;
}
not{
- $this->token = Smarty_Internal_Templateparser::TP_NOT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_NOT;
}
typecast {
- $this->token = Smarty_Internal_Templateparser::TP_TYPECAST;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TYPECAST;
}
openP {
- $this->token = Smarty_Internal_Templateparser::TP_OPENP;
+ $this->token = \Smarty\Parser\TemplateParser::TP_OPENP;
}
closeP {
- $this->token = Smarty_Internal_Templateparser::TP_CLOSEP;
+ $this->token = \Smarty\Parser\TemplateParser::TP_CLOSEP;
}
openB {
- $this->token = Smarty_Internal_Templateparser::TP_OPENB;
+ $this->token = \Smarty\Parser\TemplateParser::TP_OPENB;
}
closeB {
- $this->token = Smarty_Internal_Templateparser::TP_CLOSEB;
+ $this->token = \Smarty\Parser\TemplateParser::TP_CLOSEB;
}
ptr {
- $this->token = Smarty_Internal_Templateparser::TP_PTR;
+ $this->token = \Smarty\Parser\TemplateParser::TP_PTR;
}
aptr {
- $this->token = Smarty_Internal_Templateparser::TP_APTR;
+ $this->token = \Smarty\Parser\TemplateParser::TP_APTR;
}
equal {
- $this->token = Smarty_Internal_Templateparser::TP_EQUAL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_EQUAL;
}
incdec {
- $this->token = Smarty_Internal_Templateparser::TP_INCDEC;
+ $this->token = \Smarty\Parser\TemplateParser::TP_INCDEC;
}
unimath {
- $this->token = Smarty_Internal_Templateparser::TP_UNIMATH;
+ $this->token = \Smarty\Parser\TemplateParser::TP_UNIMATH;
}
math {
- $this->token = Smarty_Internal_Templateparser::TP_MATH;
+ $this->token = \Smarty\Parser\TemplateParser::TP_MATH;
}
at {
- $this->token = Smarty_Internal_Templateparser::TP_AT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_AT;
}
array openP {
- $this->token = Smarty_Internal_Templateparser::TP_ARRAYOPEN;
+ $this->token = \Smarty\Parser\TemplateParser::TP_ARRAYOPEN;
}
hatch {
- $this->token = Smarty_Internal_Templateparser::TP_HATCH;
+ $this->token = \Smarty\Parser\TemplateParser::TP_HATCH;
}
attr {
// resolve conflicts with shorttag and right_delimiter starting with '='
if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->compiler->getRdelLength()) === $this->smarty->getRightDelimiter()) {
preg_match('/\s+/',$this->value,$match);
$this->value = $match[0];
- $this->token = Smarty_Internal_Templateparser::TP_SPACE;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SPACE;
} else {
- $this->token = Smarty_Internal_Templateparser::TP_ATTR;
+ $this->token = \Smarty\Parser\TemplateParser::TP_ATTR;
}
}
namespace {
- $this->token = Smarty_Internal_Templateparser::TP_NAMESPACE;
+ $this->token = \Smarty\Parser\TemplateParser::TP_NAMESPACE;
}
id {
- $this->token = Smarty_Internal_Templateparser::TP_ID;
+ $this->token = \Smarty\Parser\TemplateParser::TP_ID;
}
integer {
- $this->token = Smarty_Internal_Templateparser::TP_INTEGER;
+ $this->token = \Smarty\Parser\TemplateParser::TP_INTEGER;
}
backtick {
- $this->token = Smarty_Internal_Templateparser::TP_BACKTICK;
+ $this->token = \Smarty\Parser\TemplateParser::TP_BACKTICK;
$this->yypopstate();
}
vert {
- $this->token = Smarty_Internal_Templateparser::TP_VERT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_VERT;
}
dot {
- $this->token = Smarty_Internal_Templateparser::TP_DOT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOT;
}
comma {
- $this->token = Smarty_Internal_Templateparser::TP_COMMA;
+ $this->token = \Smarty\Parser\TemplateParser::TP_COMMA;
}
semicolon {
- $this->token = Smarty_Internal_Templateparser::TP_SEMICOLON;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SEMICOLON;
}
doublecolon {
- $this->token = Smarty_Internal_Templateparser::TP_DOUBLECOLON;
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOUBLECOLON;
}
colon {
- $this->token = Smarty_Internal_Templateparser::TP_COLON;
+ $this->token = \Smarty\Parser\TemplateParser::TP_COLON;
}
qmark {
- $this->token = Smarty_Internal_Templateparser::TP_QMARK;
+ $this->token = \Smarty\Parser\TemplateParser::TP_QMARK;
}
hex {
- $this->token = Smarty_Internal_Templateparser::TP_HEX;
+ $this->token = \Smarty\Parser\TemplateParser::TP_HEX;
}
space {
- $this->token = Smarty_Internal_Templateparser::TP_SPACE;
+ $this->token = \Smarty\Parser\TemplateParser::TP_SPACE;
}
char {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
*/
@@ -616,14 +597,14 @@ class Smarty_Internal_Templatelexer
%statename LITERAL
ldel literal rdel {
$this->literal_cnt++;
- $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERAL;
}
ldel slash literal rdel {
if ($this->literal_cnt) {
$this->literal_cnt--;
- $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERAL;
} else {
- $this->token = Smarty_Internal_Templateparser::TP_LITERALEND;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERALEND;
$this->yypopstate();
}
}
@@ -639,19 +620,19 @@ class Smarty_Internal_Templatelexer
$this->compiler->trigger_template_error ("missing or misspelled literal closing tag");
}
$this->value = substr($this->data,$this->counter,$to-$this->counter);
- $this->token = Smarty_Internal_Templateparser::TP_LITERAL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LITERAL;
}
*/
/*!lex2php
%statename DOUBLEQUOTEDSTRING
userliteral {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
ldel literal rdel {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
ldel slash literal rdel {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
ldel slash {
$this->yypushstate(self::TAG);
@@ -662,33 +643,33 @@ class Smarty_Internal_Templatelexer
return true;
}
ldel {
- $this->token = Smarty_Internal_Templateparser::TP_LDEL;
+ $this->token = \Smarty\Parser\TemplateParser::TP_LDEL;
$this->taglineno = $this->line;
$this->yypushstate(self::TAGBODY);
}
double_quote {
- $this->token = Smarty_Internal_Templateparser::TP_QUOTE;
+ $this->token = \Smarty\Parser\TemplateParser::TP_QUOTE;
$this->yypopstate();
}
backtick dollar {
- $this->token = Smarty_Internal_Templateparser::TP_BACKTICK;
+ $this->token = \Smarty\Parser\TemplateParser::TP_BACKTICK;
$this->value = substr($this->value,0,-1);
$this->yypushstate(self::TAGBODY);
$this->taglineno = $this->line;
}
dollar id {
- $this->token = Smarty_Internal_Templateparser::TP_DOLLARID;
+ $this->token = \Smarty\Parser\TemplateParser::TP_DOLLARID;
}
dollar {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
textdoublequoted {
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
char {
$to = $this->dataLength;
$this->value = substr($this->data,$this->counter,$to-$this->counter);
- $this->token = Smarty_Internal_Templateparser::TP_TEXT;
+ $this->token = \Smarty\Parser\TemplateParser::TP_TEXT;
}
*/
}
diff --git a/src/includes/smarty-5.4.1/src/ParseTree/Base.php b/src/includes/smarty-5.4.1/src/ParseTree/Base.php
new file mode 100644
index 0000000..e1140c1
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/ParseTree/Base.php
@@ -0,0 +1,45 @@
+data);
}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_dq.php b/src/includes/smarty-5.4.1/src/ParseTree/Dq.php
similarity index 50%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_dq.php
rename to src/includes/smarty-5.4.1/src/ParseTree/Dq.php
index 8655f58..b5fca3b 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_dq.php
+++ b/src/includes/smarty-5.4.1/src/ParseTree/Dq.php
@@ -1,92 +1,94 @@
subtrees[] = $subtree;
- if ($subtree instanceof Smarty_Internal_ParseTree_Tag) {
- $parser->block_nesting_level = count($parser->compiler->_tag_stack);
+ if ($subtree instanceof Tag) {
+ $parser->block_nesting_level = $parser->compiler->getTagStackCount();
}
}
/**
* Append buffer to subtree
*
- * @param \Smarty_Internal_Templateparser $parser
- * @param Smarty_Internal_ParseTree $subtree parse tree buffer
+ * @param \Smarty\Parser\TemplateParser $parser
+ * @param Base $subtree parse tree buffer
*/
- public function append_subtree(Smarty_Internal_Templateparser $parser, Smarty_Internal_ParseTree $subtree)
+ public function append_subtree(\Smarty\Parser\TemplateParser $parser, Base $subtree)
{
$last_subtree = count($this->subtrees) - 1;
- if ($last_subtree >= 0 && $this->subtrees[ $last_subtree ] instanceof Smarty_Internal_ParseTree_Tag
+ if ($last_subtree >= 0 && $this->subtrees[ $last_subtree ] instanceof Tag
&& $this->subtrees[ $last_subtree ]->saved_block_nesting < $parser->block_nesting_level
) {
- if ($subtree instanceof Smarty_Internal_ParseTree_Code) {
+ if ($subtree instanceof Code) {
$this->subtrees[ $last_subtree ]->data =
$parser->compiler->appendCode(
- $this->subtrees[ $last_subtree ]->data,
+ (string) $this->subtrees[ $last_subtree ]->data,
'data . ';?>'
);
- } elseif ($subtree instanceof Smarty_Internal_ParseTree_DqContent) {
+ } elseif ($subtree instanceof DqContent) {
$this->subtrees[ $last_subtree ]->data =
$parser->compiler->appendCode(
- $this->subtrees[ $last_subtree ]->data,
+ (string) $this->subtrees[ $last_subtree ]->data,
'data . '";?>'
);
} else {
$this->subtrees[ $last_subtree ]->data =
- $parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, $subtree->data);
+ $parser->compiler->appendCode((string) $this->subtrees[ $last_subtree ]->data, (string) $subtree->data);
}
} else {
$this->subtrees[] = $subtree;
}
- if ($subtree instanceof Smarty_Internal_ParseTree_Tag) {
- $parser->block_nesting_level = count($parser->compiler->_tag_stack);
+ if ($subtree instanceof Tag) {
+ $parser->block_nesting_level = $parser->compiler->getTagStackCount();
}
}
/**
* Merge subtree buffer content together
*
- * @param \Smarty_Internal_Templateparser $parser
+ * @param \Smarty\Parser\TemplateParser $parser
*
* @return string compiled template code
*/
- public function to_smarty_php(Smarty_Internal_Templateparser $parser)
+ public function to_smarty_php(\Smarty\Parser\TemplateParser $parser)
{
$code = '';
foreach ($this->subtrees as $subtree) {
if ($code !== '') {
$code .= '.';
}
- if ($subtree instanceof Smarty_Internal_ParseTree_Tag) {
+ if ($subtree instanceof Tag) {
$more_php = $subtree->assign_to_var($parser);
} else {
$more_php = $subtree->to_smarty_php($parser);
}
$code .= $more_php;
- if (!$subtree instanceof Smarty_Internal_ParseTree_DqContent) {
+ if (!$subtree instanceof DqContent) {
$parser->compiler->has_variable_string = true;
}
}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_dqcontent.php b/src/includes/smarty-5.4.1/src/ParseTree/DqContent.php
similarity index 58%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_dqcontent.php
rename to src/includes/smarty-5.4.1/src/ParseTree/DqContent.php
index a8ca389..f0a4b06 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_dqcontent.php
+++ b/src/includes/smarty-5.4.1/src/ParseTree/DqContent.php
@@ -1,22 +1,24 @@
data . '"';
}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_tag.php b/src/includes/smarty-5.4.1/src/ParseTree/Tag.php
similarity index 63%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_tag.php
rename to src/includes/smarty-5.4.1/src/ParseTree/Tag.php
index e6c7556..05237f2 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_parsetree_tag.php
+++ b/src/includes/smarty-5.4.1/src/ParseTree/Tag.php
@@ -1,10 +1,13 @@
data = $data;
$this->saved_block_nesting = $parser->block_nesting_level;
@@ -40,11 +43,11 @@ class Smarty_Internal_ParseTree_Tag extends Smarty_Internal_ParseTree
/**
* Return buffer content
*
- * @param \Smarty_Internal_Templateparser $parser
+ * @param \Smarty\Parser\TemplateParser $parser
*
* @return string content
*/
- public function to_smarty_php(Smarty_Internal_Templateparser $parser)
+ public function to_smarty_php(\Smarty\Parser\TemplateParser $parser)
{
return $this->data;
}
@@ -52,16 +55,16 @@ class Smarty_Internal_ParseTree_Tag extends Smarty_Internal_ParseTree
/**
* Return complied code that loads the evaluated output of buffer content into a temporary variable
*
- * @param \Smarty_Internal_Templateparser $parser
+ * @param \Smarty\Parser\TemplateParser $parser
*
* @return string template code
*/
- public function assign_to_var(Smarty_Internal_Templateparser $parser)
+ public function assign_to_var(\Smarty\Parser\TemplateParser $parser)
{
$var = $parser->compiler->getNewPrefixVariable();
- $tmp = $parser->compiler->appendCode('', $this->data);
+ $tmp = $parser->compiler->appendCode('', (string) $this->data);
$tmp = $parser->compiler->appendCode($tmp, "");
- $parser->compiler->prefix_code[] = sprintf('%s', $tmp);
+ $parser->compiler->appendPrefixCode($tmp);
return $var;
}
}
diff --git a/src/includes/smarty-5.4.1/src/ParseTree/Template.php b/src/includes/smarty-5.4.1/src/ParseTree/Template.php
new file mode 100644
index 0000000..ce802a0
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/ParseTree/Template.php
@@ -0,0 +1,172 @@
+subtrees)) {
+ $this->subtrees = array_merge($this->subtrees, $subtree->subtrees);
+ } else {
+ if ($subtree->data !== '') {
+ $this->subtrees[] = $subtree;
+ }
+ }
+ }
+
+ /**
+ * Append array to subtree
+ *
+ * @param \Smarty\Parser\TemplateParser $parser
+ * @param Base[] $array
+ */
+ public function append_array(\Smarty\Parser\TemplateParser $parser, $array = array())
+ {
+ if (!empty($array)) {
+ $this->subtrees = array_merge($this->subtrees, (array)$array);
+ }
+ }
+
+ /**
+ * Prepend array to subtree
+ *
+ * @param \Smarty\Parser\TemplateParser $parser
+ * @param Base[] $array
+ */
+ public function prepend_array(\Smarty\Parser\TemplateParser $parser, $array = array())
+ {
+ if (!empty($array)) {
+ $this->subtrees = array_merge((array)$array, $this->subtrees);
+ }
+ }
+
+ /**
+ * Sanitize and merge subtree buffers together
+ *
+ * @param \Smarty\Parser\TemplateParser $parser
+ *
+ * @return string template code content
+ */
+ public function to_smarty_php(\Smarty\Parser\TemplateParser $parser)
+ {
+ $code = '';
+
+ foreach ($this->getChunkedSubtrees() as $chunk) {
+ $text = '';
+ switch ($chunk['mode']) {
+ case 'textstripped':
+ foreach ($chunk['subtrees'] as $subtree) {
+ $text .= $subtree->to_smarty_php($parser);
+ }
+ $code .= preg_replace(
+ '/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/',
+ "\n",
+ $parser->compiler->processText($text)
+ );
+ break;
+ case 'text':
+ foreach ($chunk['subtrees'] as $subtree) {
+ $text .= $subtree->to_smarty_php($parser);
+ }
+ $code .= preg_replace(
+ '/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/',
+ "\n",
+ $text
+ );
+ break;
+ case 'tag':
+ foreach ($chunk['subtrees'] as $subtree) {
+ $text = $parser->compiler->appendCode($text, (string) $subtree->to_smarty_php($parser));
+ }
+ $code .= $text;
+ break;
+ default:
+ foreach ($chunk['subtrees'] as $subtree) {
+ $text = $subtree->to_smarty_php($parser);
+ }
+ $code .= $text;
+
+ }
+ }
+ return $code;
+ }
+
+ private function getChunkedSubtrees() {
+ $chunks = array();
+ $currentMode = null;
+ $currentChunk = array();
+ for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) {
+
+ if ($this->subtrees[ $key ]->data === '' && in_array($currentMode, array('textstripped', 'text', 'tag'))) {
+ continue;
+ }
+
+ if ($this->subtrees[ $key ] instanceof Text
+ && $this->subtrees[ $key ]->isToBeStripped()) {
+ $newMode = 'textstripped';
+ } elseif ($this->subtrees[ $key ] instanceof Text) {
+ $newMode = 'text';
+ } elseif ($this->subtrees[ $key ] instanceof Tag) {
+ $newMode = 'tag';
+ } else {
+ $newMode = 'other';
+ }
+
+ if ($newMode == $currentMode) {
+ $currentChunk[] = $this->subtrees[ $key ];
+ } else {
+ $chunks[] = array(
+ 'mode' => $currentMode,
+ 'subtrees' => $currentChunk
+ );
+ $currentMode = $newMode;
+ $currentChunk = array($this->subtrees[ $key ]);
+ }
+ }
+ if ($currentMode && $currentChunk) {
+ $chunks[] = array(
+ 'mode' => $currentMode,
+ 'subtrees' => $currentChunk
+ );
+ }
+ return $chunks;
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/ParseTree/Text.php b/src/includes/smarty-5.4.1/src/ParseTree/Text.php
new file mode 100644
index 0000000..e613140
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/ParseTree/Text.php
@@ -0,0 +1,59 @@
+data = $data;
+ $this->toBeStripped = $toBeStripped;
+ }
+
+ /**
+ * Wether this section should be stripped on output to smarty php
+ * @return bool
+ */
+ public function isToBeStripped() {
+ return $this->toBeStripped;
+ }
+
+ /**
+ * Return buffer content
+ *
+ * @param \Smarty\Parser\TemplateParser $parser
+ *
+ * @return string text
+ */
+ public function to_smarty_php(\Smarty\Parser\TemplateParser $parser)
+ {
+ return $this->data;
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Parser/ConfigfileParser.php b/src/includes/smarty-5.4.1/src/Parser/ConfigfileParser.php
new file mode 100644
index 0000000..7997a09
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Parser/ConfigfileParser.php
@@ -0,0 +1,972 @@
+ '\\',
+ '\'' => '\'');
+
+ /**
+ * constructor
+ *
+ * @param Lexer $lex
+ * @param Configfile $compiler
+ */
+ public function __construct(Lexer $lex, Configfile $compiler)
+ {
+ $this->lex = $lex;
+ $this->smarty = $compiler->getSmarty();
+ $this->compiler = $compiler;
+ $this->configOverwrite = $this->smarty->config_overwrite;
+ $this->configReadHidden = $this->smarty->config_read_hidden;
+ }
+
+ /**
+ * parse optional boolean keywords
+ *
+ * @param string $str
+ *
+ * @return bool
+ */
+ private function parse_bool($str)
+ {
+ $str = strtolower($str);
+ if (in_array($str, array('on', 'yes', 'true'))) {
+ $res = true;
+ } else {
+ $res = false;
+ }
+ return $res;
+ }
+
+ /**
+ * parse single quoted string
+ * remove outer quotes
+ * unescape inner quotes
+ *
+ * @param string $qstr
+ *
+ * @return string
+ */
+ private static function parse_single_quoted_string($qstr)
+ {
+ $escaped_string = substr($qstr, 1, strlen($qstr) - 2); //remove outer quotes
+
+ $ss = preg_split('/(\\\\.)/', $escaped_string, - 1, PREG_SPLIT_DELIM_CAPTURE);
+
+ $str = '';
+ foreach ($ss as $s) {
+ if (strlen($s) === 2 && $s[0] === '\\') {
+ if (isset(self::$escapes_single[$s[1]])) {
+ $s = self::$escapes_single[$s[1]];
+ }
+ }
+ $str .= $s;
+ }
+ return $str;
+ }
+
+ /**
+ * parse double quoted string
+ *
+ * @param string $qstr
+ *
+ * @return string
+ */
+ private static function parse_double_quoted_string($qstr)
+ {
+ $inner_str = substr($qstr, 1, strlen($qstr) - 2);
+ return stripcslashes($inner_str);
+ }
+
+ /**
+ * parse triple quoted string
+ *
+ * @param string $qstr
+ *
+ * @return string
+ */
+ private static function parse_tripple_double_quoted_string($qstr)
+ {
+ return stripcslashes($qstr);
+ }
+
+ /**
+ * set a config variable in target array
+ *
+ * @param array $var
+ * @param array $target_array
+ */
+ private function set_var(array $var, array &$target_array)
+ {
+ $key = $var['key'];
+ $value = $var['value'];
+
+ if ($this->configOverwrite || !isset($target_array['vars'][$key])) {
+ $target_array['vars'][$key] = $value;
+ } else {
+ settype($target_array['vars'][$key], 'array');
+ $target_array['vars'][$key][] = $value;
+ }
+ }
+
+ /**
+ * add config variable to global vars
+ *
+ * @param array $vars
+ */
+ private function add_global_vars(array $vars)
+ {
+ if (!isset($this->compiler->config_data['vars'])) {
+ $this->compiler->config_data['vars'] = array();
+ }
+ foreach ($vars as $var) {
+ $this->set_var($var, $this->compiler->config_data);
+ }
+ }
+
+ /**
+ * add config variable to section
+ *
+ * @param string $section_name
+ * @param array $vars
+ */
+ private function add_section_vars($section_name, array $vars)
+ {
+ if (!isset($this->compiler->config_data['sections'][$section_name]['vars'])) {
+ $this->compiler->config_data['sections'][$section_name]['vars'] = array();
+ }
+ foreach ($vars as $var) {
+ $this->set_var($var, $this->compiler->config_data['sections'][$section_name]);
+ }
+ }
+
+ const TPC_OPENB = 1;
+ const TPC_SECTION = 2;
+ const TPC_CLOSEB = 3;
+ const TPC_DOT = 4;
+ const TPC_ID = 5;
+ const TPC_EQUAL = 6;
+ const TPC_FLOAT = 7;
+ const TPC_INT = 8;
+ const TPC_BOOL = 9;
+ const TPC_SINGLE_QUOTED_STRING = 10;
+ const TPC_DOUBLE_QUOTED_STRING = 11;
+ const TPC_TRIPPLE_QUOTES = 12;
+ const TPC_TRIPPLE_TEXT = 13;
+ const TPC_TRIPPLE_QUOTES_END = 14;
+ const TPC_NAKED_STRING = 15;
+ const TPC_OTHER = 16;
+ const TPC_NEWLINE = 17;
+ const TPC_COMMENTSTART = 18;
+ const YY_NO_ACTION = 60;
+ const YY_ACCEPT_ACTION = 59;
+ const YY_ERROR_ACTION = 58;
+
+ const YY_SZ_ACTTAB = 39;
+public static $yy_action = array(
+ 24, 25, 26, 27, 28, 12, 15, 23, 31, 32,
+ 59, 8, 9, 3, 21, 22, 33, 13, 33, 13,
+ 14, 10, 18, 16, 30, 11, 17, 20, 34, 7,
+ 5, 1, 2, 29, 4, 19, 52, 35, 6,
+ );
+ public static $yy_lookahead = array(
+ 7, 8, 9, 10, 11, 12, 5, 27, 15, 16,
+ 20, 21, 25, 23, 25, 26, 17, 18, 17, 18,
+ 2, 25, 4, 13, 14, 1, 15, 24, 17, 22,
+ 3, 23, 23, 14, 6, 2, 28, 17, 3,
+);
+ const YY_SHIFT_USE_DFLT = -8;
+ const YY_SHIFT_MAX = 19;
+ public static $yy_shift_ofst = array(
+ -8, 1, 1, 1, -7, -1, -1, 24, -8, -8,
+ -8, 18, 10, 11, 27, 28, 19, 20, 33, 35,
+);
+ const YY_REDUCE_USE_DFLT = -21;
+ const YY_REDUCE_MAX = 10;
+ public static $yy_reduce_ofst = array(
+ -10, -11, -11, -11, -20, -13, -4, 3, 7, 8,
+ 9,
+);
+ public static $yyExpectedTokens = array(
+ array(),
+ array(5, 17, 18, ),
+ array(5, 17, 18, ),
+ array(5, 17, 18, ),
+ array(7, 8, 9, 10, 11, 12, 15, 16, ),
+ array(17, 18, ),
+ array(17, 18, ),
+ array(1, ),
+ array(),
+ array(),
+ array(),
+ array(2, 4, ),
+ array(13, 14, ),
+ array(15, 17, ),
+ array(3, ),
+ array(6, ),
+ array(14, ),
+ array(17, ),
+ array(2, ),
+ array(3, ),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+);
+ public static $yy_default = array(
+ 44, 40, 41, 37, 58, 58, 58, 36, 39, 44,
+ 44, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 38, 42, 43, 45, 46, 47, 48, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57,
+);
+ const YYNOCODE = 29;
+ const YYSTACKDEPTH = 100;
+ const YYNSTATE = 36;
+ const YYNRULE = 22;
+ const YYERRORSYMBOL = 19;
+ const YYERRSYMDT = 'yy0';
+ const YYFALLBACK = 0;
+ public static $yyFallback = array(
+ );
+ public function Trace($TraceFILE, $zTracePrompt)
+ {
+ if (!$TraceFILE) {
+ $zTracePrompt = 0;
+ } elseif (!$zTracePrompt) {
+ $TraceFILE = 0;
+ }
+ $this->yyTraceFILE = $TraceFILE;
+ $this->yyTracePrompt = $zTracePrompt;
+ }
+
+ public function PrintTrace()
+ {
+ $this->yyTraceFILE = fopen('php://output', 'w');
+ $this->yyTracePrompt = ' ';
+ }
+
+ public $yyTraceFILE;
+ public $yyTracePrompt;
+ public $yyidx; /* Index of top element in stack */
+ public $yyerrcnt; /* Shifts left before out of the error */
+ public $yystack = array(); /* The parser's stack */
+
+ public $yyTokenName = array(
+ '$', 'OPENB', 'SECTION', 'CLOSEB',
+ 'DOT', 'ID', 'EQUAL', 'FLOAT',
+ 'INT', 'BOOL', 'SINGLE_QUOTED_STRING', 'DOUBLE_QUOTED_STRING',
+ 'TRIPPLE_QUOTES', 'TRIPPLE_TEXT', 'TRIPPLE_QUOTES_END', 'NAKED_STRING',
+ 'OTHER', 'NEWLINE', 'COMMENTSTART', 'error',
+ 'start', 'global_vars', 'sections', 'var_list',
+ 'section', 'newline', 'var', 'value',
+ );
+
+ public static $yyRuleName = array(
+ 'start ::= global_vars sections',
+ 'global_vars ::= var_list',
+ 'sections ::= sections section',
+ 'sections ::=',
+ 'section ::= OPENB SECTION CLOSEB newline var_list',
+ 'section ::= OPENB DOT SECTION CLOSEB newline var_list',
+ 'var_list ::= var_list newline',
+ 'var_list ::= var_list var',
+ 'var_list ::=',
+ 'var ::= ID EQUAL value',
+ 'value ::= FLOAT',
+ 'value ::= INT',
+ 'value ::= BOOL',
+ 'value ::= SINGLE_QUOTED_STRING',
+ 'value ::= DOUBLE_QUOTED_STRING',
+ 'value ::= TRIPPLE_QUOTES TRIPPLE_TEXT TRIPPLE_QUOTES_END',
+ 'value ::= TRIPPLE_QUOTES TRIPPLE_QUOTES_END',
+ 'value ::= NAKED_STRING',
+ 'value ::= OTHER',
+ 'newline ::= NEWLINE',
+ 'newline ::= COMMENTSTART NEWLINE',
+ 'newline ::= COMMENTSTART NAKED_STRING NEWLINE',
+ );
+
+ public function tokenName($tokenType)
+ {
+ if ($tokenType === 0) {
+ return 'End of Input';
+ }
+ if ($tokenType > 0 && $tokenType < count($this->yyTokenName)) {
+ return $this->yyTokenName[$tokenType];
+ } else {
+ return 'Unknown';
+ }
+ }
+
+ public static function yy_destructor($yymajor, $yypminor)
+ {
+ switch ($yymajor) {
+ default: break; /* If no destructor action specified: do nothing */
+ }
+ }
+
+ public function yy_pop_parser_stack()
+ {
+ if (empty($this->yystack)) {
+ return;
+ }
+ $yytos = array_pop($this->yystack);
+ if ($this->yyTraceFILE && $this->yyidx >= 0) {
+ fwrite($this->yyTraceFILE,
+ $this->yyTracePrompt . 'Popping ' . $this->yyTokenName[$yytos->major] .
+ "\n");
+ }
+ $yymajor = $yytos->major;
+ self::yy_destructor($yymajor, $yytos->minor);
+ $this->yyidx--;
+
+ return $yymajor;
+ }
+
+ public function __destruct()
+ {
+ while ($this->yystack !== Array()) {
+ $this->yy_pop_parser_stack();
+ }
+ if (is_resource($this->yyTraceFILE)) {
+ fclose($this->yyTraceFILE);
+ }
+ }
+
+ public function yy_get_expected_tokens($token)
+ {
+ static $res3 = array();
+ static $res4 = array();
+ $state = $this->yystack[$this->yyidx]->stateno;
+ $expected = self::$yyExpectedTokens[$state];
+ if (isset($res3[$state][$token])) {
+ if ($res3[$state][$token]) {
+ return $expected;
+ }
+ } else {
+ if ($res3[$state][$token] = in_array($token, self::$yyExpectedTokens[$state], true)) {
+ return $expected;
+ }
+ }
+ $stack = $this->yystack;
+ $yyidx = $this->yyidx;
+ do {
+ $yyact = $this->yy_find_shift_action($token);
+ if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
+ // reduce action
+ $done = 0;
+ do {
+ if ($done++ === 100) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // too much recursion prevents proper detection
+ // so give up
+ return array_unique($expected);
+ }
+ $yyruleno = $yyact - self::YYNSTATE;
+ $this->yyidx -= self::$yyRuleInfo[$yyruleno][1];
+ $nextstate = $this->yy_find_reduce_action(
+ $this->yystack[$this->yyidx]->stateno,
+ self::$yyRuleInfo[$yyruleno][0]);
+ if (isset(self::$yyExpectedTokens[$nextstate])) {
+ $expected = array_merge($expected, self::$yyExpectedTokens[$nextstate]);
+ if (isset($res4[$nextstate][$token])) {
+ if ($res4[$nextstate][$token]) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return array_unique($expected);
+ }
+ } else {
+ if ($res4[$nextstate][$token] = in_array($token, self::$yyExpectedTokens[$nextstate], true)) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return array_unique($expected);
+ }
+ }
+ }
+ if ($nextstate < self::YYNSTATE) {
+ // we need to shift a non-terminal
+ $this->yyidx++;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = $nextstate;
+ $x->major = self::$yyRuleInfo[$yyruleno][0];
+ $this->yystack[$this->yyidx] = $x;
+ continue 2;
+ } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // the last token was just ignored, we can't accept
+ // by ignoring input, this is in essence ignoring a
+ // syntax error!
+ return array_unique($expected);
+ } elseif ($nextstate === self::YY_NO_ACTION) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // input accepted, but not shifted (I guess)
+ return $expected;
+ } else {
+ $yyact = $nextstate;
+ }
+ } while (true);
+ }
+ break;
+ } while (true);
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+
+ return array_unique($expected);
+ }
+
+ public function yy_is_expected_token($token)
+ {
+ static $res = array();
+ static $res2 = array();
+ if ($token === 0) {
+ return true; // 0 is not part of this
+ }
+ $state = $this->yystack[$this->yyidx]->stateno;
+ if (isset($res[$state][$token])) {
+ if ($res[$state][$token]) {
+ return true;
+ }
+ } else {
+ if ($res[$state][$token] = in_array($token, self::$yyExpectedTokens[$state], true)) {
+ return true;
+ }
+ }
+ $stack = $this->yystack;
+ $yyidx = $this->yyidx;
+ do {
+ $yyact = $this->yy_find_shift_action($token);
+ if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
+ // reduce action
+ $done = 0;
+ do {
+ if ($done++ === 100) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // too much recursion prevents proper detection
+ // so give up
+ return true;
+ }
+ $yyruleno = $yyact - self::YYNSTATE;
+ $this->yyidx -= self::$yyRuleInfo[$yyruleno][1];
+ $nextstate = $this->yy_find_reduce_action(
+ $this->yystack[$this->yyidx]->stateno,
+ self::$yyRuleInfo[$yyruleno][0]);
+ if (isset($res2[$nextstate][$token])) {
+ if ($res2[$nextstate][$token]) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return true;
+ }
+ } else {
+ if ($res2[$nextstate][$token] = (isset(self::$yyExpectedTokens[$nextstate]) && in_array($token, self::$yyExpectedTokens[$nextstate], true))) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return true;
+ }
+ }
+ if ($nextstate < self::YYNSTATE) {
+ // we need to shift a non-terminal
+ $this->yyidx++;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = $nextstate;
+ $x->major = self::$yyRuleInfo[$yyruleno][0];
+ $this->yystack[$this->yyidx] = $x;
+ continue 2;
+ } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ if (!$token) {
+ // end of input: this is valid
+ return true;
+ }
+ // the last token was just ignored, we can't accept
+ // by ignoring input, this is in essence ignoring a
+ // syntax error!
+ return false;
+ } elseif ($nextstate === self::YY_NO_ACTION) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // input accepted, but not shifted (I guess)
+ return true;
+ } else {
+ $yyact = $nextstate;
+ }
+ } while (true);
+ }
+ break;
+ } while (true);
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+
+ return true;
+ }
+
+ public function yy_find_shift_action($iLookAhead)
+ {
+ $stateno = $this->yystack[$this->yyidx]->stateno;
+
+ /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */
+ if (!isset(self::$yy_shift_ofst[$stateno])) {
+ // no shift actions
+ return self::$yy_default[$stateno];
+ }
+ $i = self::$yy_shift_ofst[$stateno];
+ if ($i === self::YY_SHIFT_USE_DFLT) {
+ return self::$yy_default[$stateno];
+ }
+ if ($iLookAhead === self::YYNOCODE) {
+ return self::YY_NO_ACTION;
+ }
+ $i += $iLookAhead;
+ if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
+ self::$yy_lookahead[$i] != $iLookAhead) {
+ if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback)
+ && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) {
+ if ($this->yyTraceFILE) {
+ fwrite($this->yyTraceFILE, $this->yyTracePrompt . 'FALLBACK ' .
+ $this->yyTokenName[$iLookAhead] . ' => ' .
+ $this->yyTokenName[$iFallback] . "\n");
+ }
+
+ return $this->yy_find_shift_action($iFallback);
+ }
+
+ return self::$yy_default[$stateno];
+ } else {
+ return self::$yy_action[$i];
+ }
+ }
+
+ public function yy_find_reduce_action($stateno, $iLookAhead)
+ {
+ /* $stateno = $this->yystack[$this->yyidx]->stateno; */
+
+ if (!isset(self::$yy_reduce_ofst[$stateno])) {
+ return self::$yy_default[$stateno];
+ }
+ $i = self::$yy_reduce_ofst[$stateno];
+ if ($i === self::YY_REDUCE_USE_DFLT) {
+ return self::$yy_default[$stateno];
+ }
+ if ($iLookAhead === self::YYNOCODE) {
+ return self::YY_NO_ACTION;
+ }
+ $i += $iLookAhead;
+ if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
+ self::$yy_lookahead[$i] != $iLookAhead) {
+ return self::$yy_default[$stateno];
+ } else {
+ return self::$yy_action[$i];
+ }
+ }
+
+ public function yy_shift($yyNewState, $yyMajor, $yypMinor)
+ {
+ $this->yyidx++;
+ if ($this->yyidx >= self::YYSTACKDEPTH) {
+ $this->yyidx--;
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sStack Overflow!\n", $this->yyTracePrompt);
+ }
+ while ($this->yyidx >= 0) {
+ $this->yy_pop_parser_stack();
+ }
+// line 245 "src/Parser/ConfigfileParser.y"
+
+ $this->internalError = true;
+ $this->compiler->trigger_config_file_error('Stack overflow in configfile parser');
+
+ return;
+ }
+ $yytos = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $yytos->stateno = $yyNewState;
+ $yytos->major = $yyMajor;
+ $yytos->minor = $yypMinor;
+ $this->yystack[] = $yytos;
+ if ($this->yyTraceFILE && $this->yyidx > 0) {
+ fprintf($this->yyTraceFILE, "%sShift %d\n", $this->yyTracePrompt,
+ $yyNewState);
+ fprintf($this->yyTraceFILE, "%sStack:", $this->yyTracePrompt);
+ for ($i = 1; $i <= $this->yyidx; $i++) {
+ fprintf($this->yyTraceFILE, " %s",
+ $this->yyTokenName[$this->yystack[$i]->major]);
+ }
+ fwrite($this->yyTraceFILE,"\n");
+ }
+ }
+
+ public static $yyRuleInfo = array(
+ array( 0 => 20, 1 => 2 ),
+ array( 0 => 21, 1 => 1 ),
+ array( 0 => 22, 1 => 2 ),
+ array( 0 => 22, 1 => 0 ),
+ array( 0 => 24, 1 => 5 ),
+ array( 0 => 24, 1 => 6 ),
+ array( 0 => 23, 1 => 2 ),
+ array( 0 => 23, 1 => 2 ),
+ array( 0 => 23, 1 => 0 ),
+ array( 0 => 26, 1 => 3 ),
+ array( 0 => 27, 1 => 1 ),
+ array( 0 => 27, 1 => 1 ),
+ array( 0 => 27, 1 => 1 ),
+ array( 0 => 27, 1 => 1 ),
+ array( 0 => 27, 1 => 1 ),
+ array( 0 => 27, 1 => 3 ),
+ array( 0 => 27, 1 => 2 ),
+ array( 0 => 27, 1 => 1 ),
+ array( 0 => 27, 1 => 1 ),
+ array( 0 => 25, 1 => 1 ),
+ array( 0 => 25, 1 => 2 ),
+ array( 0 => 25, 1 => 3 ),
+ );
+
+ public static $yyReduceMap = array(
+ 0 => 0,
+ 2 => 0,
+ 3 => 0,
+ 19 => 0,
+ 20 => 0,
+ 21 => 0,
+ 1 => 1,
+ 4 => 4,
+ 5 => 5,
+ 6 => 6,
+ 7 => 7,
+ 8 => 8,
+ 9 => 9,
+ 10 => 10,
+ 11 => 11,
+ 12 => 12,
+ 13 => 13,
+ 14 => 14,
+ 15 => 15,
+ 16 => 16,
+ 17 => 17,
+ 18 => 17,
+ );
+// line 251 "src/Parser/ConfigfileParser.y"
+ public function yy_r0(){
+ $this->_retvalue = null;
+ }
+// line 256 "src/Parser/ConfigfileParser.y"
+ public function yy_r1(){
+ $this->add_global_vars($this->yystack[$this->yyidx + 0]->minor);
+ $this->_retvalue = null;
+ }
+// line 270 "src/Parser/ConfigfileParser.y"
+ public function yy_r4(){
+ $this->add_section_vars($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + 0]->minor);
+ $this->_retvalue = null;
+ }
+// line 275 "src/Parser/ConfigfileParser.y"
+ public function yy_r5(){
+ if ($this->configReadHidden) {
+ $this->add_section_vars($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + 0]->minor);
+ }
+ $this->_retvalue = null;
+ }
+// line 283 "src/Parser/ConfigfileParser.y"
+ public function yy_r6(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
+ }
+// line 287 "src/Parser/ConfigfileParser.y"
+ public function yy_r7(){
+ $this->_retvalue = array_merge($this->yystack[$this->yyidx + -1]->minor, array($this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 291 "src/Parser/ConfigfileParser.y"
+ public function yy_r8(){
+ $this->_retvalue = array();
+ }
+// line 297 "src/Parser/ConfigfileParser.y"
+ public function yy_r9(){
+ $this->_retvalue = array('key' => $this->yystack[$this->yyidx + -2]->minor, 'value' => $this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 302 "src/Parser/ConfigfileParser.y"
+ public function yy_r10(){
+ $this->_retvalue = (float) $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 306 "src/Parser/ConfigfileParser.y"
+ public function yy_r11(){
+ $this->_retvalue = (int) $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 310 "src/Parser/ConfigfileParser.y"
+ public function yy_r12(){
+ $this->_retvalue = $this->parse_bool($this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 314 "src/Parser/ConfigfileParser.y"
+ public function yy_r13(){
+ $this->_retvalue = self::parse_single_quoted_string($this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 318 "src/Parser/ConfigfileParser.y"
+ public function yy_r14(){
+ $this->_retvalue = self::parse_double_quoted_string($this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 322 "src/Parser/ConfigfileParser.y"
+ public function yy_r15(){
+ $this->_retvalue = self::parse_tripple_double_quoted_string($this->yystack[$this->yyidx + -1]->minor);
+ }
+// line 326 "src/Parser/ConfigfileParser.y"
+ public function yy_r16(){
+ $this->_retvalue = '';
+ }
+// line 330 "src/Parser/ConfigfileParser.y"
+ public function yy_r17(){
+ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
+ }
+
+ private $_retvalue;
+
+ public function yy_reduce($yyruleno)
+ {
+ if ($this->yyTraceFILE && $yyruleno >= 0
+ && $yyruleno < count(self::$yyRuleName)) {
+ fprintf($this->yyTraceFILE, "%sReduce (%d) [%s].\n",
+ $this->yyTracePrompt, $yyruleno,
+ self::$yyRuleName[$yyruleno]);
+ }
+
+ $this->_retvalue = $yy_lefthand_side = null;
+ if (isset(self::$yyReduceMap[$yyruleno])) {
+ // call the action
+ $this->_retvalue = null;
+ $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}();
+ $yy_lefthand_side = $this->_retvalue;
+ }
+ $yygoto = self::$yyRuleInfo[$yyruleno][0];
+ $yysize = self::$yyRuleInfo[$yyruleno][1];
+ $this->yyidx -= $yysize;
+ for ($i = $yysize; $i; $i--) {
+ // pop all of the right-hand side parameters
+ array_pop($this->yystack);
+ }
+ $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto);
+ if ($yyact < self::YYNSTATE) {
+ if (!$this->yyTraceFILE && $yysize) {
+ $this->yyidx++;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = $yyact;
+ $x->major = $yygoto;
+ $x->minor = $yy_lefthand_side;
+ $this->yystack[$this->yyidx] = $x;
+ } else {
+ $this->yy_shift($yyact, $yygoto, $yy_lefthand_side);
+ }
+ } elseif ($yyact === self::YYNSTATE + self::YYNRULE + 1) {
+ $this->yy_accept();
+ }
+ }
+
+ public function yy_parse_failed()
+ {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sFail!\n", $this->yyTracePrompt);
+ } while ($this->yyidx >= 0) {
+ $this->yy_pop_parser_stack();
+ }
+ }
+
+ public function yy_syntax_error($yymajor, $TOKEN)
+ {
+// line 238 "src/Parser/ConfigfileParser.y"
+
+ $this->internalError = true;
+ $this->yymajor = $yymajor;
+ $this->compiler->trigger_config_file_error();
+ }
+
+ public function yy_accept()
+ {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sAccept!\n", $this->yyTracePrompt);
+ } while ($this->yyidx >= 0) {
+ $this->yy_pop_parser_stack();
+ }
+// line 231 "src/Parser/ConfigfileParser.y"
+
+ $this->successful = !$this->internalError;
+ $this->internalError = false;
+ $this->retvalue = $this->_retvalue;
+ }
+
+ public function doParse($yymajor, $yytokenvalue)
+ {
+ $yyerrorhit = 0; /* True if yymajor has invoked an error */
+
+ if ($this->yyidx === null || $this->yyidx < 0) {
+ $this->yyidx = 0;
+ $this->yyerrcnt = -1;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = 0;
+ $x->major = 0;
+ $this->yystack = array();
+ $this->yystack[] = $x;
+ }
+ $yyendofinput = ($yymajor==0);
+
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sInput %s\n",
+ $this->yyTracePrompt, $this->yyTokenName[$yymajor]);
+ }
+
+ do {
+ $yyact = $this->yy_find_shift_action($yymajor);
+ if ($yymajor < self::YYERRORSYMBOL &&
+ !$this->yy_is_expected_token($yymajor)) {
+ // force a syntax error
+ $yyact = self::YY_ERROR_ACTION;
+ }
+ if ($yyact < self::YYNSTATE) {
+ $this->yy_shift($yyact, $yymajor, $yytokenvalue);
+ $this->yyerrcnt--;
+ if ($yyendofinput && $this->yyidx >= 0) {
+ $yymajor = 0;
+ } else {
+ $yymajor = self::YYNOCODE;
+ }
+ } elseif ($yyact < self::YYNSTATE + self::YYNRULE) {
+ $this->yy_reduce($yyact - self::YYNSTATE);
+ } elseif ($yyact === self::YY_ERROR_ACTION) {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sSyntax Error!\n",
+ $this->yyTracePrompt);
+ }
+ if (self::YYERRORSYMBOL) {
+ if ($this->yyerrcnt < 0) {
+ $this->yy_syntax_error($yymajor, $yytokenvalue);
+ }
+ $yymx = $this->yystack[$this->yyidx]->major;
+ if ($yymx === self::YYERRORSYMBOL || $yyerrorhit) {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sDiscard input token %s\n",
+ $this->yyTracePrompt, $this->yyTokenName[$yymajor]);
+ }
+ $this->yy_destructor($yymajor, $yytokenvalue);
+ $yymajor = self::YYNOCODE;
+ } else {
+ while ($this->yyidx >= 0 &&
+ $yymx !== self::YYERRORSYMBOL &&
+ ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE
+ ){
+ $this->yy_pop_parser_stack();
+ }
+ if ($this->yyidx < 0 || $yymajor==0) {
+ $this->yy_destructor($yymajor, $yytokenvalue);
+ $this->yy_parse_failed();
+ $yymajor = self::YYNOCODE;
+ } elseif ($yymx !== self::YYERRORSYMBOL) {
+ $u2 = 0;
+ $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2);
+ }
+ }
+ $this->yyerrcnt = 3;
+ $yyerrorhit = 1;
+ } else {
+ if ($this->yyerrcnt <= 0) {
+ $this->yy_syntax_error($yymajor, $yytokenvalue);
+ }
+ $this->yyerrcnt = 3;
+ $this->yy_destructor($yymajor, $yytokenvalue);
+ if ($yyendofinput) {
+ $this->yy_parse_failed();
+ }
+ $yymajor = self::YYNOCODE;
+ }
+ } else {
+ $this->yy_accept();
+ $yymajor = self::YYNOCODE;
+ }
+ } while ($yymajor !== self::YYNOCODE && $this->yyidx >= 0);
+ }
+}
+
diff --git a/src/includes/smarty-3.1.48/lexer/smarty_internal_configfileparser.y b/src/includes/smarty-5.4.1/src/Parser/ConfigfileParser.y
similarity index 91%
rename from src/includes/smarty-3.1.48/lexer/smarty_internal_configfileparser.y
rename to src/includes/smarty-5.4.1/src/Parser/ConfigfileParser.y
index c981b58..23afc2d 100644
--- a/src/includes/smarty-3.1.48/lexer/smarty_internal_configfileparser.y
+++ b/src/includes/smarty-5.4.1/src/Parser/ConfigfileParser.y
@@ -1,5 +1,5 @@
/**
-* Smarty Internal Plugin Configfileparser
+* ConfigfileParser
*
* This is the config file parser
*
@@ -10,16 +10,22 @@
*/
%name TPC_
%declare_class {
+
+namespace Smarty\Parser;
+
+use \Smarty\Lexer\ConfigfileLexer as Lexer;
+use \Smarty\Compiler\Configfile as Configfile;
+
/**
* Smarty Internal Plugin Configfileparse
*
* This is the config file parser.
-* It is generated from the smarty_internal_configfileparser.y file
+* It is generated from the ConfigfileParser.y file
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
-class Smarty_Internal_Configfileparser
+class ConfigfileParser
}
%include_class
{
@@ -42,7 +48,7 @@ class Smarty_Internal_Configfileparser
/**
* lexer object
*
- * @var Smarty_Internal_Configfilelexer
+ * @var Lexer
*/
private $lex;
/**
@@ -54,7 +60,7 @@ class Smarty_Internal_Configfileparser
/**
* compiler object
*
- * @var Smarty_Internal_Config_File_Compiler
+ * @var Configfile
*/
public $compiler = null;
/**
@@ -86,13 +92,13 @@ class Smarty_Internal_Configfileparser
/**
* constructor
*
- * @param Smarty_Internal_Configfilelexer $lex
- * @param Smarty_Internal_Config_File_Compiler $compiler
+ * @param Lexer $lex
+ * @param Configfile $compiler
*/
- public function __construct(Smarty_Internal_Configfilelexer $lex, Smarty_Internal_Config_File_Compiler $compiler)
+ public function __construct(Lexer $lex, Configfile $compiler)
{
$this->lex = $lex;
- $this->smarty = $compiler->smarty;
+ $this->smarty = $compiler->getSmarty();
$this->compiler = $compiler;
$this->configOverwrite = $this->smarty->config_overwrite;
$this->configReadHidden = $this->smarty->config_read_hidden;
@@ -237,8 +243,8 @@ class Smarty_Internal_Configfileparser
%stack_overflow
{
- $this->internalError = true;
- $this->compiler->trigger_config_file_error('Stack overflow in configfile parser');
+ $this->internalError = true;
+ $this->compiler->trigger_config_file_error('Stack overflow in configfile parser');
}
// Complete config file
diff --git a/src/includes/smarty-5.4.1/src/Parser/TemplateParser.php b/src/includes/smarty-5.4.1/src/Parser/TemplateParser.php
new file mode 100644
index 0000000..1e087c5
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Parser/TemplateParser.php
@@ -0,0 +1,3051 @@
+
+*/
+class TemplateParser
+{
+// line 35 "src/Parser/TemplateParser.y"
+
+ const ERR1 = 'Security error: Call to private object member not allowed';
+ const ERR2 = 'Security error: Call to dynamic object member not allowed';
+
+ /**
+ * result status
+ *
+ * @var bool
+ */
+ public $successful = true;
+
+ /**
+ * return value
+ *
+ * @var mixed
+ */
+ public $retvalue = 0;
+
+ /**
+ * @var
+ */
+ public $yymajor;
+
+ /**
+ * last index of array variable
+ *
+ * @var mixed
+ */
+ public $last_index;
+
+ /**
+ * last variable name
+ *
+ * @var string
+ */
+ public $last_variable;
+
+ /**
+ * root parse tree buffer
+ *
+ * @var TemplateParseTree
+ */
+ public $root_buffer;
+
+ /**
+ * current parse tree object
+ *
+ * @var \Smarty\ParseTree\Base
+ */
+ public $current_buffer;
+
+ /**
+ * lexer object
+ *
+ * @var Lexer
+ */
+ public $lex;
+
+ /**
+ * internal error flag
+ *
+ * @var bool
+ */
+ private $internalError = false;
+
+ /**
+ * {strip} status
+ *
+ * @var bool
+ */
+ public $strip = false;
+ /**
+ * compiler object
+ *
+ * @var TemplateCompiler
+ */
+ public $compiler = null;
+
+ /**
+ * smarty object
+ *
+ * @var \Smarty\Smarty
+ */
+ public $smarty = null;
+
+ /**
+ * template object
+ *
+ * @var \Smarty\Template
+ */
+ public $template = null;
+
+ /**
+ * block nesting level
+ *
+ * @var int
+ */
+ public $block_nesting_level = 0;
+
+ /**
+ * security object
+ *
+ * @var \Smarty\Security
+ */
+ public $security = null;
+
+ /**
+ * template prefix array
+ *
+ * @var \Smarty\ParseTree\Base[]
+ */
+ public $template_prefix = array();
+
+ /**
+ * template prefix array
+ *
+ * @var \Smarty\ParseTree\Base[]
+ */
+ public $template_postfix = array();
+
+ /**
+ * constructor
+ *
+ * @param Lexer $lex
+ * @param TemplateCompiler $compiler
+ */
+ public function __construct(Lexer $lex, TemplateCompiler $compiler)
+ {
+ $this->lex = $lex;
+ $this->compiler = $compiler;
+ $this->template = $this->compiler->getTemplate();
+ $this->smarty = $this->template->getSmarty();
+ $this->security = $this->smarty->security_policy ?? false;
+ $this->current_buffer = $this->root_buffer = new TemplateParseTree();
+ }
+
+ /**
+ * insert PHP code in current buffer
+ *
+ * @param string $code
+ */
+ public function insertPhpCode($code)
+ {
+ $this->current_buffer->append_subtree($this, new Tag($this, $code));
+ }
+
+ /**
+ * error rundown
+ *
+ */
+ public function errorRunDown()
+ {
+ while ($this->yystack !== array()) {
+ $this->yy_pop_parser_stack();
+ }
+ if (is_resource($this->yyTraceFILE)) {
+ fclose($this->yyTraceFILE);
+ }
+ }
+
+ /**
+ * merge PHP code with prefix code and return parse tree tag object
+ *
+ * @param string $code
+ *
+ * @return Tag
+ */
+ private function mergePrefixCode($code)
+ {
+ $tmp = '';
+ foreach ($this->compiler->prefix_code as $preCode) {
+ $tmp .= $preCode;
+ }
+ $this->compiler->prefix_code = array();
+ $tmp .= $code;
+ return new Tag($this, $this->compiler->processNocacheCode($tmp));
+ }
+
+
+ const TP_VERT = 1;
+ const TP_COLON = 2;
+ const TP_TEXT = 3;
+ const TP_STRIPON = 4;
+ const TP_STRIPOFF = 5;
+ const TP_LITERALSTART = 6;
+ const TP_LITERALEND = 7;
+ const TP_LITERAL = 8;
+ const TP_SIMPELOUTPUT = 9;
+ const TP_SIMPLETAG = 10;
+ const TP_SMARTYBLOCKCHILDPARENT = 11;
+ const TP_LDEL = 12;
+ const TP_RDEL = 13;
+ const TP_DOLLARID = 14;
+ const TP_EQUAL = 15;
+ const TP_ID = 16;
+ const TP_PTR = 17;
+ const TP_LDELIF = 18;
+ const TP_LDELFOR = 19;
+ const TP_SEMICOLON = 20;
+ const TP_INCDEC = 21;
+ const TP_TO = 22;
+ const TP_STEP = 23;
+ const TP_LDELFOREACH = 24;
+ const TP_SPACE = 25;
+ const TP_AS = 26;
+ const TP_APTR = 27;
+ const TP_LDELSETFILTER = 28;
+ const TP_CLOSETAG = 29;
+ const TP_LDELSLASH = 30;
+ const TP_ATTR = 31;
+ const TP_INTEGER = 32;
+ const TP_COMMA = 33;
+ const TP_OPENP = 34;
+ const TP_CLOSEP = 35;
+ const TP_MATH = 36;
+ const TP_UNIMATH = 37;
+ const TP_ISIN = 38;
+ const TP_QMARK = 39;
+ const TP_NOT = 40;
+ const TP_TYPECAST = 41;
+ const TP_HEX = 42;
+ const TP_DOT = 43;
+ const TP_INSTANCEOF = 44;
+ const TP_SINGLEQUOTESTRING = 45;
+ const TP_DOUBLECOLON = 46;
+ const TP_NAMESPACE = 47;
+ const TP_AT = 48;
+ const TP_HATCH = 49;
+ const TP_OPENB = 50;
+ const TP_CLOSEB = 51;
+ const TP_DOLLAR = 52;
+ const TP_LOGOP = 53;
+ const TP_SLOGOP = 54;
+ const TP_TLOGOP = 55;
+ const TP_SINGLECOND = 56;
+ const TP_ARRAYOPEN = 57;
+ const TP_QUOTE = 58;
+ const TP_BACKTICK = 59;
+ const YY_NO_ACTION = 527;
+ const YY_ACCEPT_ACTION = 526;
+ const YY_ERROR_ACTION = 525;
+
+ const YY_SZ_ACTTAB = 2372;
+public static $yy_action = array(
+ 33, 197, 264, 299, 176, 298, 259, 242, 243, 244,
+ 1, 259, 135, 232, 199, 354, 6, 84, 495, 217,
+ 331, 354, 109, 104, 393, 248, 212, 256, 213, 51,
+ 219, 393, 21, 393, 51, 43, 393, 32, 44, 45,
+ 273, 221, 393, 277, 393, 200, 393, 83, 4, 136,
+ 295, 226, 149, 99, 220, 5, 52, 242, 243, 244,
+ 1, 307, 132, 211, 190, 9, 6, 84, 241, 217,
+ 211, 126, 109, 150, 261, 252, 212, 256, 213, 137,
+ 205, 98, 21, 313, 83, 43, 13, 295, 44, 45,
+ 273, 221, 260, 230, 197, 200, 293, 83, 4, 321,
+ 295, 35, 149, 86, 309, 5, 52, 242, 243, 244,
+ 1, 146, 97, 387, 82, 231, 6, 84, 14, 217,
+ 138, 251, 109, 148, 15, 387, 212, 256, 213, 452,
+ 219, 387, 21, 251, 439, 43, 452, 252, 44, 45,
+ 273, 221, 3, 277, 99, 200, 439, 83, 4, 252,
+ 295, 259, 526, 96, 252, 5, 52, 242, 243, 244,
+ 1, 136, 134, 262, 199, 103, 6, 84, 155, 217,
+ 252, 279, 109, 112, 51, 439, 212, 256, 213, 127,
+ 219, 316, 21, 99, 228, 43, 314, 439, 44, 45,
+ 273, 221, 318, 277, 263, 200, 83, 83, 4, 295,
+ 295, 46, 22, 280, 40, 5, 52, 242, 243, 244,
+ 1, 20, 134, 189, 191, 266, 6, 84, 254, 217,
+ 250, 19, 109, 152, 141, 253, 212, 256, 213, 197,
+ 219, 267, 21, 251, 251, 43, 175, 298, 44, 45,
+ 273, 221, 151, 277, 108, 200, 91, 83, 4, 87,
+ 295, 295, 251, 354, 180, 5, 52, 242, 243, 244,
+ 1, 259, 133, 140, 199, 354, 6, 84, 307, 217,
+ 211, 354, 109, 181, 197, 39, 212, 256, 213, 286,
+ 219, 14, 11, 94, 51, 43, 88, 15, 44, 45,
+ 273, 221, 153, 277, 143, 200, 92, 83, 4, 139,
+ 295, 295, 251, 154, 104, 5, 52, 242, 243, 244,
+ 1, 303, 134, 251, 186, 173, 6, 84, 36, 217,
+ 99, 126, 109, 181, 227, 285, 212, 256, 213, 137,
+ 208, 98, 21, 127, 180, 43, 13, 295, 44, 45,
+ 273, 221, 181, 277, 232, 200, 293, 83, 4, 112,
+ 295, 234, 196, 297, 104, 5, 52, 242, 243, 244,
+ 1, 29, 134, 224, 184, 156, 6, 84, 468, 217,
+ 197, 468, 109, 197, 23, 468, 212, 256, 213, 264,
+ 219, 18, 21, 175, 298, 43, 215, 15, 44, 45,
+ 273, 221, 232, 277, 170, 200, 168, 83, 4, 233,
+ 295, 295, 104, 144, 99, 5, 52, 242, 243, 244,
+ 1, 259, 134, 251, 199, 157, 6, 84, 26, 217,
+ 161, 181, 109, 181, 255, 439, 212, 256, 213, 178,
+ 185, 240, 21, 112, 51, 43, 164, 439, 44, 45,
+ 273, 221, 174, 277, 222, 200, 251, 83, 4, 305,
+ 295, 41, 42, 281, 12, 5, 52, 242, 243, 244,
+ 1, 197, 136, 163, 199, 167, 6, 84, 288, 289,
+ 290, 291, 109, 17, 304, 251, 212, 256, 213, 330,
+ 219, 16, 21, 258, 171, 47, 180, 25, 44, 45,
+ 273, 221, 39, 277, 93, 200, 255, 83, 4, 328,
+ 295, 41, 42, 281, 12, 5, 52, 242, 243, 244,
+ 1, 181, 136, 439, 199, 214, 6, 84, 288, 289,
+ 290, 291, 109, 177, 298, 439, 212, 256, 213, 28,
+ 219, 8, 21, 209, 194, 43, 89, 295, 44, 45,
+ 273, 221, 452, 277, 24, 200, 296, 83, 4, 452,
+ 295, 7, 440, 239, 240, 5, 52, 283, 210, 211,
+ 247, 95, 90, 106, 440, 188, 100, 81, 10, 9,
+ 254, 310, 98, 19, 294, 268, 269, 253, 195, 158,
+ 113, 169, 276, 201, 278, 172, 284, 293, 283, 210,
+ 211, 247, 197, 90, 106, 238, 187, 100, 58, 24,
+ 34, 322, 220, 98, 358, 159, 268, 269, 225, 223,
+ 317, 245, 179, 276, 201, 278, 14, 284, 293, 246,
+ 110, 283, 15, 211, 249, 439, 111, 106, 220, 188,
+ 100, 81, 24, 257, 323, 254, 98, 439, 19, 268,
+ 269, 118, 253, 265, 270, 272, 276, 201, 278, 7,
+ 284, 293, 283, 220, 211, 274, 292, 111, 85, 229,
+ 198, 116, 70, 275, 319, 160, 329, 98, 162, 320,
+ 268, 269, 36, 145, 216, 37, 332, 276, 201, 278,
+ 303, 284, 293, 41, 42, 281, 12, 303, 303, 283,
+ 303, 211, 204, 312, 111, 303, 303, 198, 116, 70,
+ 288, 289, 290, 291, 98, 303, 303, 268, 269, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 303, 303, 283, 303, 211, 303, 303, 105, 203,
+ 312, 198, 119, 49, 303, 117, 303, 303, 98, 303,
+ 254, 268, 269, 19, 303, 303, 303, 253, 276, 201,
+ 278, 303, 284, 293, 303, 283, 14, 211, 147, 303,
+ 111, 303, 15, 198, 119, 65, 197, 303, 303, 303,
+ 98, 303, 468, 268, 269, 468, 197, 303, 355, 468,
+ 276, 201, 278, 303, 284, 293, 303, 303, 389, 283,
+ 355, 211, 207, 303, 111, 303, 355, 198, 119, 65,
+ 389, 303, 303, 303, 98, 303, 389, 268, 269, 303,
+ 197, 468, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 303, 386, 283, 303, 211, 202, 303, 111, 303,
+ 303, 198, 116, 70, 386, 303, 303, 303, 98, 303,
+ 386, 268, 269, 303, 303, 303, 303, 303, 276, 201,
+ 278, 303, 284, 293, 303, 303, 303, 283, 303, 211,
+ 303, 303, 111, 303, 311, 198, 119, 65, 303, 303,
+ 303, 303, 98, 303, 303, 268, 269, 303, 303, 303,
+ 303, 303, 276, 201, 278, 303, 284, 293, 303, 303,
+ 303, 283, 303, 211, 206, 303, 105, 303, 303, 198,
+ 119, 56, 303, 233, 303, 303, 98, 303, 303, 268,
+ 269, 303, 303, 303, 303, 303, 276, 201, 278, 303,
+ 284, 293, 303, 283, 303, 211, 303, 303, 111, 303,
+ 303, 198, 115, 62, 303, 303, 303, 303, 98, 303,
+ 303, 268, 269, 303, 303, 303, 303, 303, 276, 201,
+ 278, 303, 284, 293, 303, 303, 303, 283, 303, 211,
+ 303, 303, 111, 303, 303, 193, 114, 57, 303, 303,
+ 303, 303, 98, 303, 303, 268, 269, 303, 303, 303,
+ 303, 303, 276, 201, 278, 303, 284, 293, 303, 283,
+ 303, 211, 303, 303, 111, 303, 303, 198, 101, 80,
+ 303, 303, 303, 303, 98, 303, 303, 268, 269, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 303, 303, 283, 303, 211, 303, 303, 111, 303,
+ 303, 198, 102, 79, 303, 303, 303, 303, 98, 303,
+ 303, 268, 269, 303, 303, 303, 303, 303, 276, 201,
+ 278, 303, 284, 293, 303, 283, 303, 211, 303, 303,
+ 111, 303, 303, 198, 119, 53, 303, 303, 303, 303,
+ 98, 303, 303, 268, 269, 303, 303, 303, 303, 303,
+ 276, 201, 278, 303, 284, 293, 303, 303, 303, 283,
+ 303, 211, 303, 303, 111, 303, 303, 198, 119, 64,
+ 303, 303, 303, 303, 98, 303, 303, 268, 269, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 283, 303, 211, 303, 303, 111, 303, 303, 198,
+ 101, 54, 303, 303, 303, 303, 98, 303, 303, 268,
+ 269, 303, 303, 303, 303, 303, 276, 201, 278, 303,
+ 284, 293, 303, 303, 303, 283, 303, 211, 303, 303,
+ 111, 303, 303, 198, 119, 63, 303, 303, 303, 303,
+ 98, 303, 303, 268, 269, 303, 303, 303, 303, 303,
+ 276, 201, 278, 303, 284, 293, 303, 283, 303, 211,
+ 303, 303, 111, 303, 303, 198, 119, 55, 303, 303,
+ 303, 303, 98, 303, 303, 268, 269, 303, 303, 303,
+ 303, 303, 276, 201, 278, 303, 284, 293, 303, 303,
+ 303, 283, 303, 211, 303, 303, 111, 303, 303, 198,
+ 119, 56, 303, 303, 303, 303, 98, 303, 303, 268,
+ 269, 303, 303, 303, 303, 303, 276, 201, 278, 303,
+ 284, 293, 303, 283, 303, 211, 303, 303, 111, 303,
+ 303, 198, 119, 66, 303, 303, 303, 303, 98, 303,
+ 303, 268, 269, 303, 303, 303, 303, 303, 276, 201,
+ 278, 303, 284, 293, 303, 303, 303, 283, 303, 211,
+ 303, 303, 111, 303, 303, 198, 119, 67, 303, 303,
+ 303, 303, 98, 303, 303, 268, 269, 303, 303, 303,
+ 303, 303, 276, 201, 278, 303, 284, 293, 303, 283,
+ 303, 211, 303, 303, 111, 303, 303, 198, 119, 68,
+ 303, 303, 303, 303, 98, 303, 303, 268, 269, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 303, 303, 283, 303, 211, 303, 303, 111, 303,
+ 303, 198, 119, 69, 303, 303, 303, 303, 98, 303,
+ 303, 268, 269, 303, 303, 303, 303, 303, 276, 201,
+ 278, 303, 284, 293, 303, 283, 303, 211, 303, 303,
+ 111, 303, 303, 198, 119, 71, 303, 303, 303, 303,
+ 98, 303, 303, 268, 269, 303, 303, 303, 303, 303,
+ 276, 201, 278, 303, 284, 293, 303, 303, 303, 283,
+ 303, 211, 303, 303, 111, 303, 303, 192, 119, 59,
+ 303, 303, 303, 303, 98, 303, 303, 268, 269, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 283, 303, 211, 303, 303, 111, 303, 303, 198,
+ 119, 60, 303, 303, 303, 303, 98, 303, 303, 268,
+ 269, 303, 303, 303, 303, 303, 276, 201, 278, 303,
+ 284, 293, 303, 303, 303, 283, 303, 211, 303, 303,
+ 111, 303, 303, 198, 119, 61, 303, 303, 303, 303,
+ 98, 303, 303, 268, 269, 303, 303, 303, 303, 303,
+ 276, 201, 278, 303, 284, 293, 303, 283, 303, 211,
+ 303, 303, 111, 303, 303, 198, 119, 72, 303, 303,
+ 303, 303, 98, 303, 303, 268, 269, 303, 303, 303,
+ 303, 303, 276, 201, 278, 303, 284, 293, 303, 303,
+ 303, 283, 303, 211, 303, 303, 111, 303, 303, 198,
+ 119, 73, 303, 303, 303, 303, 98, 303, 303, 268,
+ 269, 303, 303, 303, 303, 303, 276, 201, 278, 303,
+ 284, 293, 303, 283, 303, 211, 303, 303, 111, 303,
+ 303, 198, 119, 74, 303, 303, 303, 303, 98, 303,
+ 303, 268, 269, 303, 303, 303, 303, 303, 276, 201,
+ 278, 303, 284, 293, 303, 303, 303, 283, 303, 211,
+ 303, 303, 111, 303, 303, 198, 119, 75, 303, 303,
+ 303, 303, 98, 303, 303, 268, 269, 303, 303, 303,
+ 303, 303, 276, 201, 278, 303, 284, 293, 303, 283,
+ 303, 211, 303, 303, 111, 303, 303, 198, 119, 76,
+ 303, 303, 303, 303, 98, 303, 303, 268, 269, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 303, 303, 283, 303, 211, 303, 303, 111, 303,
+ 303, 198, 119, 77, 303, 303, 303, 303, 98, 303,
+ 303, 268, 269, 303, 303, 303, 303, 303, 276, 201,
+ 278, 303, 284, 293, 303, 283, 303, 211, 303, 303,
+ 111, 303, 303, 198, 119, 78, 303, 303, 303, 303,
+ 98, 303, 303, 268, 269, 303, 303, 303, 303, 303,
+ 276, 201, 278, 303, 284, 293, 303, 303, 303, 283,
+ 303, 211, 303, 303, 111, 303, 303, 198, 119, 48,
+ 303, 303, 303, 303, 98, 303, 303, 268, 269, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 303, 283, 303, 211, 303, 303, 111, 303, 303, 198,
+ 119, 50, 303, 303, 303, 303, 98, 303, 303, 268,
+ 269, 303, 303, 303, 303, 303, 276, 201, 278, 303,
+ 284, 293, 308, 303, 303, 303, 303, 303, 242, 243,
+ 244, 2, 303, 306, 303, 303, 303, 6, 84, 254,
+ 303, 303, 19, 109, 303, 303, 253, 212, 256, 213,
+ 303, 303, 38, 303, 14, 14, 303, 303, 303, 165,
+ 15, 15, 303, 303, 303, 41, 42, 281, 12, 251,
+ 303, 303, 46, 22, 280, 40, 303, 301, 27, 303,
+ 303, 308, 288, 289, 290, 291, 303, 242, 243, 244,
+ 2, 303, 306, 303, 303, 303, 6, 84, 303, 303,
+ 303, 303, 109, 303, 14, 303, 212, 256, 213, 303,
+ 15, 142, 303, 303, 303, 41, 42, 281, 12, 303,
+ 303, 251, 303, 303, 46, 22, 280, 40, 303, 303,
+ 303, 303, 288, 289, 290, 291, 302, 27, 303, 303,
+ 235, 236, 237, 130, 303, 303, 242, 243, 244, 1,
+ 468, 303, 303, 468, 303, 6, 84, 468, 452, 303,
+ 303, 109, 303, 303, 303, 212, 256, 213, 283, 303,
+ 211, 303, 303, 111, 303, 303, 198, 131, 303, 303,
+ 303, 303, 303, 98, 452, 303, 303, 452, 303, 468,
+ 303, 452, 326, 276, 201, 278, 303, 284, 293, 303,
+ 218, 303, 303, 283, 303, 211, 303, 468, 111, 303,
+ 468, 198, 125, 3, 468, 452, 303, 303, 98, 271,
+ 303, 303, 303, 303, 303, 303, 303, 282, 276, 201,
+ 278, 303, 284, 293, 283, 303, 211, 303, 303, 111,
+ 166, 452, 198, 129, 452, 303, 468, 303, 452, 98,
+ 251, 303, 303, 46, 22, 280, 40, 303, 303, 276,
+ 201, 278, 303, 284, 293, 303, 218, 303, 303, 283,
+ 303, 211, 303, 468, 111, 303, 468, 198, 120, 35,
+ 468, 452, 303, 303, 98, 271, 303, 303, 303, 303,
+ 303, 303, 303, 303, 276, 201, 278, 303, 284, 293,
+ 283, 303, 211, 303, 303, 111, 303, 452, 198, 121,
+ 452, 303, 468, 303, 452, 98, 303, 303, 303, 303,
+ 303, 303, 303, 303, 303, 276, 201, 278, 303, 284,
+ 293, 303, 218, 303, 303, 283, 303, 211, 303, 468,
+ 111, 303, 468, 198, 122, 303, 468, 452, 303, 303,
+ 98, 271, 303, 303, 303, 303, 303, 303, 303, 303,
+ 276, 201, 278, 303, 284, 293, 283, 303, 211, 303,
+ 303, 111, 303, 452, 198, 123, 452, 303, 468, 303,
+ 452, 98, 303, 303, 303, 303, 303, 303, 303, 303,
+ 303, 276, 201, 278, 303, 284, 293, 303, 30, 303,
+ 303, 283, 303, 211, 218, 468, 111, 303, 468, 198,
+ 124, 468, 468, 452, 468, 303, 98, 271, 468, 452,
+ 303, 303, 303, 271, 303, 303, 276, 201, 278, 303,
+ 284, 293, 283, 402, 211, 303, 303, 111, 303, 452,
+ 198, 128, 452, 303, 468, 452, 452, 98, 452, 303,
+ 468, 303, 452, 287, 303, 107, 325, 276, 201, 278,
+ 303, 284, 293, 303, 303, 439, 303, 402, 402, 402,
+ 402, 41, 42, 281, 12, 303, 303, 439, 303, 41,
+ 42, 281, 12, 303, 402, 402, 402, 402, 288, 289,
+ 290, 291, 41, 42, 281, 12, 288, 289, 290, 291,
+ 300, 324, 41, 42, 281, 12, 182, 315, 303, 288,
+ 289, 290, 291, 183, 303, 303, 303, 303, 303, 288,
+ 289, 290, 291, 41, 42, 281, 12, 31, 303, 41,
+ 42, 281, 12, 303, 327, 303, 41, 42, 281, 12,
+ 288, 289, 290, 291, 303, 303, 288, 289, 290, 291,
+ 303, 303, 303, 288, 289, 290, 291, 41, 42, 281,
+ 12, 41, 42, 281, 12, 303, 303, 303, 303, 303,
+ 303, 303, 303, 303, 288, 289, 290, 291, 288, 289,
+ 290, 291,
+ );
+ public static $yy_lookahead = array(
+ 2, 1, 97, 13, 99, 100, 21, 9, 10, 11,
+ 12, 21, 14, 70, 16, 25, 18, 19, 1, 21,
+ 77, 31, 24, 80, 13, 69, 28, 29, 30, 44,
+ 32, 20, 34, 22, 44, 37, 25, 39, 40, 41,
+ 42, 43, 31, 45, 33, 47, 35, 49, 50, 14,
+ 52, 16, 96, 17, 43, 57, 58, 9, 10, 11,
+ 12, 65, 14, 67, 16, 33, 18, 19, 65, 21,
+ 67, 70, 24, 96, 73, 98, 28, 29, 30, 43,
+ 32, 80, 34, 51, 49, 37, 50, 52, 40, 41,
+ 42, 43, 91, 45, 1, 47, 95, 49, 50, 51,
+ 52, 15, 96, 107, 108, 57, 58, 9, 10, 11,
+ 12, 72, 14, 13, 16, 15, 18, 19, 25, 21,
+ 80, 82, 24, 72, 31, 25, 28, 29, 30, 43,
+ 32, 31, 34, 82, 34, 37, 50, 98, 40, 41,
+ 42, 43, 15, 45, 17, 47, 46, 49, 50, 98,
+ 52, 21, 61, 62, 98, 57, 58, 9, 10, 11,
+ 12, 14, 14, 16, 16, 80, 18, 19, 96, 21,
+ 98, 93, 24, 46, 44, 34, 28, 29, 30, 101,
+ 32, 51, 34, 17, 43, 37, 101, 46, 40, 41,
+ 42, 43, 51, 45, 47, 47, 49, 49, 50, 52,
+ 52, 85, 86, 87, 88, 57, 58, 9, 10, 11,
+ 12, 12, 14, 14, 16, 16, 18, 19, 9, 21,
+ 82, 12, 24, 72, 72, 16, 28, 29, 30, 1,
+ 32, 32, 34, 82, 82, 37, 99, 100, 40, 41,
+ 42, 43, 72, 45, 79, 47, 76, 49, 50, 80,
+ 52, 52, 82, 13, 103, 57, 58, 9, 10, 11,
+ 12, 21, 14, 14, 16, 25, 18, 19, 65, 21,
+ 67, 31, 24, 103, 1, 2, 28, 29, 30, 51,
+ 32, 25, 34, 34, 44, 37, 80, 31, 40, 41,
+ 42, 43, 72, 45, 70, 47, 76, 49, 50, 14,
+ 52, 52, 82, 72, 80, 57, 58, 9, 10, 11,
+ 12, 108, 14, 82, 16, 76, 18, 19, 15, 21,
+ 17, 70, 24, 103, 73, 93, 28, 29, 30, 43,
+ 32, 80, 34, 101, 103, 37, 50, 52, 40, 41,
+ 42, 43, 103, 45, 70, 47, 95, 49, 50, 46,
+ 52, 77, 78, 69, 80, 57, 58, 9, 10, 11,
+ 12, 12, 14, 14, 16, 16, 18, 19, 9, 21,
+ 1, 12, 24, 1, 2, 16, 28, 29, 30, 97,
+ 32, 25, 34, 99, 100, 37, 17, 31, 40, 41,
+ 42, 43, 70, 45, 76, 47, 76, 49, 50, 77,
+ 52, 52, 80, 72, 17, 57, 58, 9, 10, 11,
+ 12, 21, 14, 82, 16, 96, 18, 19, 27, 21,
+ 96, 103, 24, 103, 104, 34, 28, 29, 30, 6,
+ 32, 8, 34, 46, 44, 37, 72, 46, 40, 41,
+ 42, 43, 14, 45, 16, 47, 82, 49, 50, 59,
+ 52, 36, 37, 38, 39, 57, 58, 9, 10, 11,
+ 12, 1, 14, 96, 16, 72, 18, 19, 53, 54,
+ 55, 56, 24, 15, 59, 82, 28, 29, 30, 21,
+ 32, 20, 34, 16, 76, 37, 103, 27, 40, 41,
+ 42, 43, 2, 45, 33, 47, 104, 49, 50, 14,
+ 52, 36, 37, 38, 39, 57, 58, 9, 10, 11,
+ 12, 103, 14, 34, 16, 48, 18, 19, 53, 54,
+ 55, 56, 24, 99, 100, 46, 28, 29, 30, 12,
+ 32, 34, 34, 63, 64, 37, 96, 52, 40, 41,
+ 42, 43, 43, 45, 33, 47, 35, 49, 50, 50,
+ 52, 34, 34, 7, 8, 57, 58, 65, 66, 67,
+ 68, 81, 70, 71, 46, 73, 74, 75, 34, 33,
+ 9, 35, 80, 12, 100, 83, 84, 16, 64, 96,
+ 46, 81, 90, 91, 92, 81, 94, 95, 65, 66,
+ 67, 68, 1, 70, 71, 7, 73, 74, 75, 33,
+ 15, 35, 43, 80, 13, 96, 83, 84, 17, 48,
+ 51, 13, 16, 90, 91, 92, 25, 94, 95, 13,
+ 16, 65, 31, 67, 68, 34, 70, 71, 43, 73,
+ 74, 75, 33, 16, 35, 9, 80, 46, 12, 83,
+ 84, 16, 16, 16, 14, 16, 90, 91, 92, 34,
+ 94, 95, 65, 43, 67, 32, 16, 70, 16, 16,
+ 73, 74, 75, 32, 51, 49, 16, 80, 49, 51,
+ 83, 84, 15, 26, 48, 22, 35, 90, 91, 92,
+ 109, 94, 95, 36, 37, 38, 39, 109, 109, 65,
+ 109, 67, 105, 106, 70, 109, 109, 73, 74, 75,
+ 53, 54, 55, 56, 80, 109, 109, 83, 84, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 109, 109, 65, 109, 67, 109, 109, 70, 105,
+ 106, 73, 74, 75, 109, 77, 109, 109, 80, 109,
+ 9, 83, 84, 12, 109, 109, 109, 16, 90, 91,
+ 92, 109, 94, 95, 109, 65, 25, 67, 27, 109,
+ 70, 109, 31, 73, 74, 75, 1, 109, 109, 109,
+ 80, 109, 9, 83, 84, 12, 1, 109, 13, 16,
+ 90, 91, 92, 109, 94, 95, 109, 109, 13, 65,
+ 25, 67, 102, 109, 70, 109, 31, 73, 74, 75,
+ 25, 109, 109, 109, 80, 109, 31, 83, 84, 109,
+ 1, 48, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 109, 13, 65, 109, 67, 102, 109, 70, 109,
+ 109, 73, 74, 75, 25, 109, 109, 109, 80, 109,
+ 31, 83, 84, 109, 109, 109, 109, 109, 90, 91,
+ 92, 109, 94, 95, 109, 109, 109, 65, 109, 67,
+ 109, 109, 70, 109, 106, 73, 74, 75, 109, 109,
+ 109, 109, 80, 109, 109, 83, 84, 109, 109, 109,
+ 109, 109, 90, 91, 92, 109, 94, 95, 109, 109,
+ 109, 65, 109, 67, 102, 109, 70, 109, 109, 73,
+ 74, 75, 109, 77, 109, 109, 80, 109, 109, 83,
+ 84, 109, 109, 109, 109, 109, 90, 91, 92, 109,
+ 94, 95, 109, 65, 109, 67, 109, 109, 70, 109,
+ 109, 73, 74, 75, 109, 109, 109, 109, 80, 109,
+ 109, 83, 84, 109, 109, 109, 109, 109, 90, 91,
+ 92, 109, 94, 95, 109, 109, 109, 65, 109, 67,
+ 109, 109, 70, 109, 109, 73, 74, 75, 109, 109,
+ 109, 109, 80, 109, 109, 83, 84, 109, 109, 109,
+ 109, 109, 90, 91, 92, 109, 94, 95, 109, 65,
+ 109, 67, 109, 109, 70, 109, 109, 73, 74, 75,
+ 109, 109, 109, 109, 80, 109, 109, 83, 84, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 109, 109, 65, 109, 67, 109, 109, 70, 109,
+ 109, 73, 74, 75, 109, 109, 109, 109, 80, 109,
+ 109, 83, 84, 109, 109, 109, 109, 109, 90, 91,
+ 92, 109, 94, 95, 109, 65, 109, 67, 109, 109,
+ 70, 109, 109, 73, 74, 75, 109, 109, 109, 109,
+ 80, 109, 109, 83, 84, 109, 109, 109, 109, 109,
+ 90, 91, 92, 109, 94, 95, 109, 109, 109, 65,
+ 109, 67, 109, 109, 70, 109, 109, 73, 74, 75,
+ 109, 109, 109, 109, 80, 109, 109, 83, 84, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 65, 109, 67, 109, 109, 70, 109, 109, 73,
+ 74, 75, 109, 109, 109, 109, 80, 109, 109, 83,
+ 84, 109, 109, 109, 109, 109, 90, 91, 92, 109,
+ 94, 95, 109, 109, 109, 65, 109, 67, 109, 109,
+ 70, 109, 109, 73, 74, 75, 109, 109, 109, 109,
+ 80, 109, 109, 83, 84, 109, 109, 109, 109, 109,
+ 90, 91, 92, 109, 94, 95, 109, 65, 109, 67,
+ 109, 109, 70, 109, 109, 73, 74, 75, 109, 109,
+ 109, 109, 80, 109, 109, 83, 84, 109, 109, 109,
+ 109, 109, 90, 91, 92, 109, 94, 95, 109, 109,
+ 109, 65, 109, 67, 109, 109, 70, 109, 109, 73,
+ 74, 75, 109, 109, 109, 109, 80, 109, 109, 83,
+ 84, 109, 109, 109, 109, 109, 90, 91, 92, 109,
+ 94, 95, 109, 65, 109, 67, 109, 109, 70, 109,
+ 109, 73, 74, 75, 109, 109, 109, 109, 80, 109,
+ 109, 83, 84, 109, 109, 109, 109, 109, 90, 91,
+ 92, 109, 94, 95, 109, 109, 109, 65, 109, 67,
+ 109, 109, 70, 109, 109, 73, 74, 75, 109, 109,
+ 109, 109, 80, 109, 109, 83, 84, 109, 109, 109,
+ 109, 109, 90, 91, 92, 109, 94, 95, 109, 65,
+ 109, 67, 109, 109, 70, 109, 109, 73, 74, 75,
+ 109, 109, 109, 109, 80, 109, 109, 83, 84, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 109, 109, 65, 109, 67, 109, 109, 70, 109,
+ 109, 73, 74, 75, 109, 109, 109, 109, 80, 109,
+ 109, 83, 84, 109, 109, 109, 109, 109, 90, 91,
+ 92, 109, 94, 95, 109, 65, 109, 67, 109, 109,
+ 70, 109, 109, 73, 74, 75, 109, 109, 109, 109,
+ 80, 109, 109, 83, 84, 109, 109, 109, 109, 109,
+ 90, 91, 92, 109, 94, 95, 109, 109, 109, 65,
+ 109, 67, 109, 109, 70, 109, 109, 73, 74, 75,
+ 109, 109, 109, 109, 80, 109, 109, 83, 84, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 65, 109, 67, 109, 109, 70, 109, 109, 73,
+ 74, 75, 109, 109, 109, 109, 80, 109, 109, 83,
+ 84, 109, 109, 109, 109, 109, 90, 91, 92, 109,
+ 94, 95, 109, 109, 109, 65, 109, 67, 109, 109,
+ 70, 109, 109, 73, 74, 75, 109, 109, 109, 109,
+ 80, 109, 109, 83, 84, 109, 109, 109, 109, 109,
+ 90, 91, 92, 109, 94, 95, 109, 65, 109, 67,
+ 109, 109, 70, 109, 109, 73, 74, 75, 109, 109,
+ 109, 109, 80, 109, 109, 83, 84, 109, 109, 109,
+ 109, 109, 90, 91, 92, 109, 94, 95, 109, 109,
+ 109, 65, 109, 67, 109, 109, 70, 109, 109, 73,
+ 74, 75, 109, 109, 109, 109, 80, 109, 109, 83,
+ 84, 109, 109, 109, 109, 109, 90, 91, 92, 109,
+ 94, 95, 109, 65, 109, 67, 109, 109, 70, 109,
+ 109, 73, 74, 75, 109, 109, 109, 109, 80, 109,
+ 109, 83, 84, 109, 109, 109, 109, 109, 90, 91,
+ 92, 109, 94, 95, 109, 109, 109, 65, 109, 67,
+ 109, 109, 70, 109, 109, 73, 74, 75, 109, 109,
+ 109, 109, 80, 109, 109, 83, 84, 109, 109, 109,
+ 109, 109, 90, 91, 92, 109, 94, 95, 109, 65,
+ 109, 67, 109, 109, 70, 109, 109, 73, 74, 75,
+ 109, 109, 109, 109, 80, 109, 109, 83, 84, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 109, 109, 65, 109, 67, 109, 109, 70, 109,
+ 109, 73, 74, 75, 109, 109, 109, 109, 80, 109,
+ 109, 83, 84, 109, 109, 109, 109, 109, 90, 91,
+ 92, 109, 94, 95, 109, 65, 109, 67, 109, 109,
+ 70, 109, 109, 73, 74, 75, 109, 109, 109, 109,
+ 80, 109, 109, 83, 84, 109, 109, 109, 109, 109,
+ 90, 91, 92, 109, 94, 95, 109, 109, 109, 65,
+ 109, 67, 109, 109, 70, 109, 109, 73, 74, 75,
+ 109, 109, 109, 109, 80, 109, 109, 83, 84, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 109, 65, 109, 67, 109, 109, 70, 109, 109, 73,
+ 74, 75, 109, 109, 109, 109, 80, 109, 109, 83,
+ 84, 109, 109, 109, 109, 109, 90, 91, 92, 109,
+ 94, 95, 3, 109, 109, 109, 109, 109, 9, 10,
+ 11, 12, 109, 14, 109, 109, 109, 18, 19, 9,
+ 109, 109, 12, 24, 109, 109, 16, 28, 29, 30,
+ 109, 109, 23, 109, 25, 25, 109, 109, 109, 72,
+ 31, 31, 109, 109, 109, 36, 37, 38, 39, 82,
+ 109, 109, 85, 86, 87, 88, 109, 58, 59, 109,
+ 109, 3, 53, 54, 55, 56, 109, 9, 10, 11,
+ 12, 109, 14, 109, 109, 109, 18, 19, 109, 109,
+ 109, 109, 24, 109, 25, 109, 28, 29, 30, 109,
+ 31, 72, 109, 109, 109, 36, 37, 38, 39, 109,
+ 109, 82, 109, 109, 85, 86, 87, 88, 109, 109,
+ 109, 109, 53, 54, 55, 56, 58, 59, 109, 109,
+ 3, 4, 5, 6, 109, 109, 9, 10, 11, 12,
+ 9, 109, 109, 12, 109, 18, 19, 16, 17, 109,
+ 109, 24, 109, 109, 109, 28, 29, 30, 65, 109,
+ 67, 109, 109, 70, 109, 109, 73, 74, 109, 109,
+ 109, 109, 109, 80, 43, 109, 109, 46, 109, 48,
+ 109, 50, 89, 90, 91, 92, 109, 94, 95, 109,
+ 2, 109, 109, 65, 109, 67, 109, 9, 70, 109,
+ 12, 73, 74, 15, 16, 17, 109, 109, 80, 21,
+ 109, 109, 109, 109, 109, 109, 109, 89, 90, 91,
+ 92, 109, 94, 95, 65, 109, 67, 109, 109, 70,
+ 72, 43, 73, 74, 46, 109, 48, 109, 50, 80,
+ 82, 109, 109, 85, 86, 87, 88, 109, 109, 90,
+ 91, 92, 109, 94, 95, 109, 2, 109, 109, 65,
+ 109, 67, 109, 9, 70, 109, 12, 73, 74, 15,
+ 16, 17, 109, 109, 80, 21, 109, 109, 109, 109,
+ 109, 109, 109, 109, 90, 91, 92, 109, 94, 95,
+ 65, 109, 67, 109, 109, 70, 109, 43, 73, 74,
+ 46, 109, 48, 109, 50, 80, 109, 109, 109, 109,
+ 109, 109, 109, 109, 109, 90, 91, 92, 109, 94,
+ 95, 109, 2, 109, 109, 65, 109, 67, 109, 9,
+ 70, 109, 12, 73, 74, 109, 16, 17, 109, 109,
+ 80, 21, 109, 109, 109, 109, 109, 109, 109, 109,
+ 90, 91, 92, 109, 94, 95, 65, 109, 67, 109,
+ 109, 70, 109, 43, 73, 74, 46, 109, 48, 109,
+ 50, 80, 109, 109, 109, 109, 109, 109, 109, 109,
+ 109, 90, 91, 92, 109, 94, 95, 109, 2, 109,
+ 109, 65, 109, 67, 2, 9, 70, 109, 12, 73,
+ 74, 9, 16, 17, 12, 109, 80, 21, 16, 17,
+ 109, 109, 109, 21, 109, 109, 90, 91, 92, 109,
+ 94, 95, 65, 2, 67, 109, 109, 70, 109, 43,
+ 73, 74, 46, 109, 48, 43, 50, 80, 46, 109,
+ 48, 109, 50, 51, 109, 20, 13, 90, 91, 92,
+ 109, 94, 95, 109, 109, 34, 109, 36, 37, 38,
+ 39, 36, 37, 38, 39, 109, 109, 46, 109, 36,
+ 37, 38, 39, 109, 53, 54, 55, 56, 53, 54,
+ 55, 56, 36, 37, 38, 39, 53, 54, 55, 56,
+ 13, 35, 36, 37, 38, 39, 13, 51, 109, 53,
+ 54, 55, 56, 13, 109, 109, 109, 109, 109, 53,
+ 54, 55, 56, 36, 37, 38, 39, 2, 109, 36,
+ 37, 38, 39, 109, 13, 109, 36, 37, 38, 39,
+ 53, 54, 55, 56, 109, 109, 53, 54, 55, 56,
+ 109, 109, 109, 53, 54, 55, 56, 36, 37, 38,
+ 39, 36, 37, 38, 39, 109, 109, 109, 109, 109,
+ 109, 109, 109, 109, 53, 54, 55, 56, 53, 54,
+ 55, 56,
+);
+ const YY_SHIFT_USE_DFLT = -16;
+ const YY_SHIFT_MAX = 234;
+ public static $yy_shift_ofst = array(
+ -16, 98, 98, 148, 198, 198, 248, 148, 148, 198,
+ 148, 248, -2, 48, 298, 148, 148, 148, 298, 148,
+ 148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
+ 348, 148, 148, 148, 148, 398, 148, 148, 148, 448,
+ 498, 498, 498, 498, 498, 498, 498, 498, 1819, 1869,
+ 1869, 147, 1809, 2225, 647, 2233, 2256, 2246, 2277, 415,
+ 2283, 2290, 2315, 2311, 465, 465, 465, 465, 465, 465,
+ 465, 465, 465, 465, 465, 465, 465, 465, 465, 465,
+ 465, 465, 591, 35, 249, 93, 1868, 731, 1820, 36,
+ 127, 93, 93, 249, 249, 273, 1927, 1988, 561, 349,
+ 765, 775, 809, 209, 209, 303, 256, 285, 256, 356,
+ 369, 387, 428, 428, 228, 372, 460, 256, 0, 0,
+ 0, 0, 0, 0, 0, 0, 166, 166, 17, 0,
+ -16, -16, 2192, 2054, 2120, 2186, 1931, 199, 626, 359,
+ 86, 256, 256, 458, 256, 485, 256, 485, 256, 286,
+ 286, 256, 256, 256, 256, 286, 517, 286, 286, 286,
+ 499, 286, 499, 286, 256, 256, 256, 256, 0, 490,
+ 0, 0, 490, 0, 497, 166, 166, 166, -16, -16,
+ -16, -16, -16, -16, 2221, 11, 100, -10, 240, 763,
+ 141, 391, 390, 130, 423, 546, 461, 467, -15, 479,
+ 518, 534, 511, 536, 32, 559, 566, 599, 585, 588,
+ 598, 606, 596, 604, 617, 625, 627, 630, 629, 610,
+ 623, 631, 615, 640, 497, 642, 616, 619, 643, 613,
+ 618, 650, 657, 641, 653,
+);
+ const YY_REDUCE_USE_DFLT = -96;
+ const YY_REDUCE_MAX = 183;
+ public static $yy_reduce_ofst = array(
+ 91, 492, 523, 556, 587, 624, 658, 690, 724, 758,
+ 792, 826, 858, 892, 924, 958, 990, 1024, 1056, 1090,
+ 1122, 1156, 1188, 1222, 1254, 1288, 1320, 1354, 1386, 1420,
+ 1452, 1486, 1518, 1552, 1584, 1618, 1650, 1684, 1716, 1893,
+ 1928, 1959, 1994, 2025, 2060, 2091, 2126, 2157, 1777, 1829,
+ 1958, 1, -4, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 116, 116, 116, 116, 116, 116, 116, 116,
+ 116, 116, 170, 251, 274, 220, 203, 39, 51, -95,
+ 284, 151, 231, -57, 322, 320, 3, -44, -23, 85,
+ 239, 239, 239, 72, -23, 137, 152, 224, 331, 364,
+ 318, 137, 78, 232, 239, 239, 239, 393, 408, 239,
+ 239, 239, 239, 239, 239, 239, 137, 424, 239, 239,
+ 470, 239, 6, 6, 6, 6, 6, 40, 56, 6,
+ 6, 138, 138, 165, 138, 169, 138, 206, 138, 282,
+ 282, 138, 138, 138, 138, 282, 319, 282, 282, 282,
+ 324, 282, 367, 282, 138, 138, 138, 138, 383, 392,
+ 383, 383, 392, 383, 440, 474, 474, 474, 514, 480,
+ 500, 504, 483, 509,
+);
+ public static $yyExpectedTokens = array(
+ array(),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(2, 9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 39, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 51, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 21, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(9, 10, 11, 12, 14, 16, 18, 19, 24, 28, 29, 30, 32, 34, 37, 40, 41, 42, 43, 45, 47, 49, 50, 52, 57, 58, ),
+ array(23, 25, 31, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(25, 31, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(25, 31, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(14, 16, 47, 49, 52, ),
+ array(3, 9, 10, 11, 12, 14, 18, 19, 24, 28, 29, 30, 58, 59, ),
+ array(20, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(26, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(13, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(35, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 51, 53, 54, 55, 56, ),
+ array(13, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, 59, ),
+ array(13, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(13, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(2, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(13, 36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(36, 37, 38, 39, 53, 54, 55, 56, ),
+ array(1, 13, 17, 25, 31, 34, 46, ),
+ array(14, 16, 49, 52, ),
+ array(14, 34, 52, ),
+ array(1, 25, 31, ),
+ array(3, 9, 10, 11, 12, 14, 18, 19, 24, 28, 29, 30, 58, 59, ),
+ array(9, 12, 16, 25, 27, 31, ),
+ array(9, 12, 16, 25, 31, ),
+ array(17, 43, 50, ),
+ array(15, 17, 46, ),
+ array(1, 25, 31, ),
+ array(1, 25, 31, ),
+ array(14, 34, 52, ),
+ array(14, 34, 52, ),
+ array(1, 2, ),
+ array(3, 4, 5, 6, 9, 10, 11, 12, 18, 19, 24, 28, 29, 30, ),
+ array(2, 9, 12, 15, 16, 17, 21, 43, 46, 48, 50, ),
+ array(9, 12, 16, 48, ),
+ array(12, 14, 16, 52, ),
+ array(1, 13, 25, 31, ),
+ array(1, 13, 25, 31, ),
+ array(1, 13, 25, 31, ),
+ array(9, 12, 16, ),
+ array(9, 12, 16, ),
+ array(15, 17, 46, ),
+ array(25, 31, ),
+ array(14, 52, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(1, 17, ),
+ array(17, 46, ),
+ array(14, 16, ),
+ array(14, 16, ),
+ array(1, 51, ),
+ array(1, 2, ),
+ array(1, 27, ),
+ array(25, 31, ),
+ array(1, ),
+ array(1, ),
+ array(1, ),
+ array(1, ),
+ array(1, ),
+ array(1, ),
+ array(1, ),
+ array(1, ),
+ array(17, ),
+ array(17, ),
+ array(1, ),
+ array(1, ),
+ array(),
+ array(),
+ array(2, 9, 12, 16, 17, 21, 43, 46, 48, 50, 51, ),
+ array(2, 9, 12, 15, 16, 17, 21, 43, 46, 48, 50, ),
+ array(2, 9, 12, 16, 17, 21, 43, 46, 48, 50, ),
+ array(2, 9, 12, 16, 17, 21, 43, 46, 48, 50, ),
+ array(9, 12, 16, 17, 43, 46, 48, 50, ),
+ array(12, 14, 16, 32, 52, ),
+ array(9, 12, 16, 48, ),
+ array(9, 12, 16, ),
+ array(15, 43, 50, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(15, 21, ),
+ array(25, 31, ),
+ array(14, 52, ),
+ array(25, 31, ),
+ array(14, 52, ),
+ array(25, 31, ),
+ array(43, 50, ),
+ array(43, 50, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(43, 50, ),
+ array(12, 34, ),
+ array(43, 50, ),
+ array(43, 50, ),
+ array(43, 50, ),
+ array(43, 50, ),
+ array(43, 50, ),
+ array(43, 50, ),
+ array(43, 50, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(25, 31, ),
+ array(1, ),
+ array(2, ),
+ array(1, ),
+ array(1, ),
+ array(2, ),
+ array(1, ),
+ array(34, ),
+ array(17, ),
+ array(17, ),
+ array(17, ),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(2, 34, 36, 37, 38, 39, 46, 53, 54, 55, 56, ),
+ array(13, 20, 22, 25, 31, 33, 35, 43, ),
+ array(13, 15, 25, 31, 34, 46, ),
+ array(13, 21, 25, 31, 44, ),
+ array(13, 21, 25, 31, 44, ),
+ array(9, 12, 16, 48, ),
+ array(34, 43, 46, 51, ),
+ array(27, 34, 46, ),
+ array(21, 44, 59, ),
+ array(21, 44, 51, ),
+ array(6, 8, ),
+ array(7, 8, ),
+ array(20, 33, ),
+ array(16, 48, ),
+ array(21, 44, ),
+ array(34, 46, ),
+ array(34, 46, ),
+ array(34, 46, ),
+ array(33, 35, ),
+ array(33, 35, ),
+ array(33, 51, ),
+ array(43, 51, ),
+ array(33, 35, ),
+ array(33, 35, ),
+ array(15, 43, ),
+ array(7, ),
+ array(13, ),
+ array(13, ),
+ array(16, ),
+ array(16, ),
+ array(16, ),
+ array(16, ),
+ array(16, ),
+ array(14, ),
+ array(16, ),
+ array(43, ),
+ array(32, ),
+ array(32, ),
+ array(34, ),
+ array(16, ),
+ array(34, ),
+ array(16, ),
+ array(49, ),
+ array(49, ),
+ array(16, ),
+ array(51, ),
+ array(51, ),
+ array(16, ),
+ array(15, ),
+ array(35, ),
+ array(22, ),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+ array(),
+);
+ public static $yy_default = array(
+ 343, 525, 525, 525, 510, 510, 525, 487, 487, 525,
+ 487, 525, 525, 525, 525, 525, 525, 525, 525, 525,
+ 525, 525, 525, 525, 525, 525, 525, 525, 525, 525,
+ 525, 525, 525, 525, 525, 525, 525, 525, 525, 525,
+ 525, 525, 525, 525, 525, 525, 525, 525, 383, 362,
+ 383, 525, 525, 525, 388, 525, 525, 525, 356, 525,
+ 525, 525, 525, 525, 367, 486, 406, 413, 485, 511,
+ 513, 512, 412, 414, 411, 415, 390, 394, 395, 385,
+ 388, 356, 426, 525, 525, 383, 525, 383, 383, 500,
+ 442, 383, 383, 525, 525, 374, 333, 441, 452, 525,
+ 397, 397, 397, 452, 452, 442, 383, 525, 383, 383,
+ 377, 442, 525, 525, 397, 397, 397, 364, 379, 397,
+ 404, 417, 418, 419, 405, 410, 442, 497, 417, 403,
+ 341, 494, 441, 441, 441, 441, 441, 525, 454, 452,
+ 468, 353, 363, 525, 366, 525, 371, 525, 372, 449,
+ 450, 357, 359, 360, 361, 478, 452, 477, 480, 479,
+ 445, 446, 447, 448, 373, 369, 370, 365, 375, 488,
+ 378, 380, 489, 435, 452, 474, 501, 498, 341, 493,
+ 493, 493, 452, 452, 426, 422, 426, 416, 416, 453,
+ 426, 426, 416, 416, 339, 525, 525, 525, 416, 426,
+ 436, 525, 525, 525, 525, 422, 525, 525, 422, 525,
+ 525, 525, 525, 525, 525, 525, 525, 525, 525, 422,
+ 424, 525, 499, 525, 468, 525, 525, 525, 525, 525,
+ 431, 525, 525, 525, 391, 334, 335, 336, 337, 338,
+ 340, 342, 344, 345, 346, 347, 348, 349, 350, 352,
+ 381, 382, 470, 471, 472, 492, 376, 490, 491, 420,
+ 429, 430, 439, 440, 451, 455, 456, 457, 398, 399,
+ 400, 401, 402, 421, 423, 425, 427, 431, 432, 433,
+ 407, 408, 409, 434, 437, 438, 465, 463, 502, 503,
+ 504, 505, 443, 444, 476, 469, 484, 351, 475, 521,
+ 522, 514, 515, 516, 519, 518, 520, 523, 524, 517,
+ 507, 509, 508, 506, 481, 466, 464, 462, 459, 460,
+ 461, 467, 482, 483, 428, 458, 496, 473, 468, 384,
+ 368, 392, 396,
+);
+ const YYNOCODE = 110;
+ const YYSTACKDEPTH = 500;
+ const YYNSTATE = 333;
+ const YYNRULE = 192;
+ const YYERRORSYMBOL = 60;
+ const YYERRSYMDT = 'yy0';
+ const YYFALLBACK = 0;
+ public static $yyFallback = array(
+ );
+ public function Trace($TraceFILE, $zTracePrompt)
+ {
+ if (!$TraceFILE) {
+ $zTracePrompt = 0;
+ } elseif (!$zTracePrompt) {
+ $TraceFILE = 0;
+ }
+ $this->yyTraceFILE = $TraceFILE;
+ $this->yyTracePrompt = $zTracePrompt;
+ }
+
+ public function PrintTrace()
+ {
+ $this->yyTraceFILE = fopen('php://output', 'w');
+ $this->yyTracePrompt = ' ';
+ }
+
+ public $yyTraceFILE;
+ public $yyTracePrompt;
+ public $yyidx; /* Index of top element in stack */
+ public $yyerrcnt; /* Shifts left before out of the error */
+ public $yystack = array(); /* The parser's stack */
+
+ public $yyTokenName = array(
+ '$', 'VERT', 'COLON', 'TEXT',
+ 'STRIPON', 'STRIPOFF', 'LITERALSTART', 'LITERALEND',
+ 'LITERAL', 'SIMPELOUTPUT', 'SIMPLETAG', 'SMARTYBLOCKCHILDPARENT',
+ 'LDEL', 'RDEL', 'DOLLARID', 'EQUAL',
+ 'ID', 'PTR', 'LDELIF', 'LDELFOR',
+ 'SEMICOLON', 'INCDEC', 'TO', 'STEP',
+ 'LDELFOREACH', 'SPACE', 'AS', 'APTR',
+ 'LDELSETFILTER', 'CLOSETAG', 'LDELSLASH', 'ATTR',
+ 'INTEGER', 'COMMA', 'OPENP', 'CLOSEP',
+ 'MATH', 'UNIMATH', 'ISIN', 'QMARK',
+ 'NOT', 'TYPECAST', 'HEX', 'DOT',
+ 'INSTANCEOF', 'SINGLEQUOTESTRING', 'DOUBLECOLON', 'NAMESPACE',
+ 'AT', 'HATCH', 'OPENB', 'CLOSEB',
+ 'DOLLAR', 'LOGOP', 'SLOGOP', 'TLOGOP',
+ 'SINGLECOND', 'ARRAYOPEN', 'QUOTE', 'BACKTICK',
+ 'error', 'start', 'template', 'literal_e2',
+ 'literal_e1', 'smartytag', 'tagbody', 'tag',
+ 'outattr', 'eqoutattr', 'varindexed', 'output',
+ 'attributes', 'variable', 'value', 'expr',
+ 'modifierlist', 'statement', 'statements', 'foraction',
+ 'varvar', 'modparameters', 'attribute', 'nullcoalescing',
+ 'ternary', 'tlop', 'lop', 'scond',
+ 'isin', 'array', 'function', 'ns1',
+ 'doublequoted_with_quotes', 'static_class_access', 'arraydef', 'object',
+ 'arrayindex', 'indexdef', 'varvarele', 'objectchain',
+ 'objectelement', 'method', 'params', 'modifier',
+ 'modparameter', 'arrayelements', 'arrayelement', 'doublequoted',
+ 'doublequotedcontent',
+ );
+
+ public static $yyRuleName = array(
+ 'start ::= template',
+ 'template ::= template TEXT',
+ 'template ::= template STRIPON',
+ 'template ::= template STRIPOFF',
+ 'template ::= template LITERALSTART literal_e2 LITERALEND',
+ 'literal_e2 ::= literal_e1 LITERALSTART literal_e1 LITERALEND',
+ 'literal_e2 ::= literal_e1',
+ 'literal_e1 ::= literal_e1 LITERAL',
+ 'literal_e1 ::=',
+ 'template ::= template smartytag',
+ 'template ::=',
+ 'smartytag ::= SIMPELOUTPUT',
+ 'smartytag ::= SIMPLETAG',
+ 'smartytag ::= SMARTYBLOCKCHILDPARENT',
+ 'smartytag ::= LDEL tagbody RDEL',
+ 'smartytag ::= tag RDEL',
+ 'tagbody ::= outattr',
+ 'tagbody ::= DOLLARID eqoutattr',
+ 'tagbody ::= varindexed eqoutattr',
+ 'eqoutattr ::= EQUAL outattr',
+ 'outattr ::= output attributes',
+ 'output ::= variable',
+ 'output ::= value',
+ 'output ::= expr',
+ 'tag ::= LDEL ID attributes',
+ 'tag ::= LDEL ID',
+ 'tag ::= LDEL ID modifierlist attributes',
+ 'tag ::= LDEL ID PTR ID attributes',
+ 'tag ::= LDEL ID PTR ID modifierlist attributes',
+ 'tag ::= LDELIF expr',
+ 'tag ::= LDELIF expr attributes',
+ 'tag ::= LDELIF statement',
+ 'tag ::= LDELIF statement attributes',
+ 'tag ::= LDELFOR statements SEMICOLON expr SEMICOLON varindexed foraction attributes',
+ 'foraction ::= EQUAL expr',
+ 'foraction ::= INCDEC',
+ 'tag ::= LDELFOR statement TO expr attributes',
+ 'tag ::= LDELFOR statement TO expr STEP expr attributes',
+ 'tag ::= LDELFOREACH SPACE expr AS varvar attributes',
+ 'tag ::= LDELFOREACH SPACE expr AS varvar APTR varvar attributes',
+ 'tag ::= LDELFOREACH attributes',
+ 'tag ::= LDELSETFILTER ID modparameters',
+ 'tag ::= LDELSETFILTER ID modparameters modifierlist',
+ 'smartytag ::= CLOSETAG',
+ 'tag ::= LDELSLASH ID',
+ 'tag ::= LDELSLASH ID modifierlist',
+ 'tag ::= LDELSLASH ID PTR ID',
+ 'tag ::= LDELSLASH ID PTR ID modifierlist',
+ 'attributes ::= attributes attribute',
+ 'attributes ::= attribute',
+ 'attributes ::=',
+ 'attribute ::= SPACE ID EQUAL ID',
+ 'attribute ::= ATTR expr',
+ 'attribute ::= ATTR value',
+ 'attribute ::= SPACE ID',
+ 'attribute ::= SPACE expr',
+ 'attribute ::= SPACE value',
+ 'attribute ::= SPACE INTEGER EQUAL expr',
+ 'statements ::= statement',
+ 'statements ::= statements COMMA statement',
+ 'statement ::= DOLLARID EQUAL INTEGER',
+ 'statement ::= DOLLARID EQUAL expr',
+ 'statement ::= varindexed EQUAL expr',
+ 'statement ::= OPENP statement CLOSEP',
+ 'expr ::= value',
+ 'expr ::= nullcoalescing',
+ 'expr ::= ternary',
+ 'expr ::= INCDEC DOLLARID',
+ 'expr ::= DOLLARID INCDEC',
+ 'expr ::= DOLLARID COLON ID',
+ 'expr ::= expr MATH value',
+ 'expr ::= expr UNIMATH value',
+ 'expr ::= expr tlop value',
+ 'expr ::= expr lop expr',
+ 'expr ::= expr scond',
+ 'isin ::= ISIN',
+ 'expr ::= expr isin array',
+ 'expr ::= expr isin value',
+ 'nullcoalescing ::= expr QMARK QMARK expr',
+ 'ternary ::= expr QMARK DOLLARID COLON expr',
+ 'ternary ::= expr QMARK value COLON expr',
+ 'ternary ::= expr QMARK expr COLON expr',
+ 'ternary ::= expr QMARK COLON expr',
+ 'value ::= variable',
+ 'value ::= UNIMATH value',
+ 'value ::= NOT value',
+ 'value ::= TYPECAST value',
+ 'value ::= variable INCDEC',
+ 'value ::= HEX',
+ 'value ::= INTEGER',
+ 'value ::= INTEGER DOT INTEGER',
+ 'value ::= INTEGER DOT',
+ 'value ::= DOT INTEGER',
+ 'value ::= ID',
+ 'value ::= function',
+ 'value ::= OPENP expr CLOSEP',
+ 'value ::= variable INSTANCEOF ns1',
+ 'value ::= variable INSTANCEOF variable',
+ 'value ::= SINGLEQUOTESTRING',
+ 'value ::= doublequoted_with_quotes',
+ 'value ::= varindexed DOUBLECOLON static_class_access',
+ 'value ::= smartytag',
+ 'value ::= value modifierlist',
+ 'value ::= NAMESPACE',
+ 'value ::= arraydef',
+ 'value ::= ns1 DOUBLECOLON static_class_access',
+ 'ns1 ::= ID',
+ 'ns1 ::= NAMESPACE',
+ 'variable ::= DOLLARID',
+ 'variable ::= varindexed',
+ 'variable ::= varvar AT ID',
+ 'variable ::= object',
+ 'variable ::= HATCH ID HATCH',
+ 'variable ::= HATCH ID HATCH arrayindex',
+ 'variable ::= HATCH variable HATCH',
+ 'variable ::= HATCH variable HATCH arrayindex',
+ 'varindexed ::= DOLLARID arrayindex',
+ 'varindexed ::= varvar arrayindex',
+ 'arrayindex ::= arrayindex indexdef',
+ 'arrayindex ::=',
+ 'indexdef ::= DOT DOLLARID',
+ 'indexdef ::= DOT varvar',
+ 'indexdef ::= DOT varvar AT ID',
+ 'indexdef ::= DOT ID',
+ 'indexdef ::= DOT INTEGER',
+ 'indexdef ::= DOT LDEL expr RDEL',
+ 'indexdef ::= OPENB ID CLOSEB',
+ 'indexdef ::= OPENB ID DOT ID CLOSEB',
+ 'indexdef ::= OPENB SINGLEQUOTESTRING CLOSEB',
+ 'indexdef ::= OPENB INTEGER CLOSEB',
+ 'indexdef ::= OPENB DOLLARID CLOSEB',
+ 'indexdef ::= OPENB variable CLOSEB',
+ 'indexdef ::= OPENB value CLOSEB',
+ 'indexdef ::= OPENB expr CLOSEB',
+ 'indexdef ::= OPENB CLOSEB',
+ 'varvar ::= DOLLARID',
+ 'varvar ::= DOLLAR',
+ 'varvar ::= varvar varvarele',
+ 'varvarele ::= ID',
+ 'varvarele ::= SIMPELOUTPUT',
+ 'varvarele ::= LDEL expr RDEL',
+ 'object ::= varindexed objectchain',
+ 'objectchain ::= objectelement',
+ 'objectchain ::= objectchain objectelement',
+ 'objectelement ::= PTR ID arrayindex',
+ 'objectelement ::= PTR varvar arrayindex',
+ 'objectelement ::= PTR LDEL expr RDEL arrayindex',
+ 'objectelement ::= PTR ID LDEL expr RDEL arrayindex',
+ 'objectelement ::= PTR method',
+ 'function ::= ns1 OPENP params CLOSEP',
+ 'method ::= ID OPENP params CLOSEP',
+ 'method ::= DOLLARID OPENP params CLOSEP',
+ 'params ::= params COMMA expr',
+ 'params ::= expr',
+ 'params ::=',
+ 'modifierlist ::= modifierlist modifier modparameters',
+ 'modifierlist ::= modifier modparameters',
+ 'modifier ::= VERT AT ID',
+ 'modifier ::= VERT ID',
+ 'modparameters ::= modparameters modparameter',
+ 'modparameters ::=',
+ 'modparameter ::= COLON value',
+ 'modparameter ::= COLON UNIMATH value',
+ 'modparameter ::= COLON array',
+ 'static_class_access ::= method',
+ 'static_class_access ::= method objectchain',
+ 'static_class_access ::= ID',
+ 'static_class_access ::= DOLLARID arrayindex',
+ 'static_class_access ::= DOLLARID arrayindex objectchain',
+ 'lop ::= LOGOP',
+ 'lop ::= SLOGOP',
+ 'tlop ::= TLOGOP',
+ 'scond ::= SINGLECOND',
+ 'arraydef ::= OPENB arrayelements CLOSEB',
+ 'arraydef ::= ARRAYOPEN arrayelements CLOSEP',
+ 'arrayelements ::= arrayelement',
+ 'arrayelements ::= arrayelements COMMA arrayelement',
+ 'arrayelements ::=',
+ 'arrayelement ::= value APTR expr',
+ 'arrayelement ::= ID APTR expr',
+ 'arrayelement ::= expr',
+ 'doublequoted_with_quotes ::= QUOTE QUOTE',
+ 'doublequoted_with_quotes ::= QUOTE doublequoted QUOTE',
+ 'doublequoted ::= doublequoted doublequotedcontent',
+ 'doublequoted ::= doublequotedcontent',
+ 'doublequotedcontent ::= BACKTICK variable BACKTICK',
+ 'doublequotedcontent ::= BACKTICK expr BACKTICK',
+ 'doublequotedcontent ::= DOLLARID',
+ 'doublequotedcontent ::= LDEL variable RDEL',
+ 'doublequotedcontent ::= LDEL expr RDEL',
+ 'doublequotedcontent ::= smartytag',
+ 'doublequotedcontent ::= TEXT',
+ );
+
+ public function tokenName($tokenType)
+ {
+ if ($tokenType === 0) {
+ return 'End of Input';
+ }
+ if ($tokenType > 0 && $tokenType < count($this->yyTokenName)) {
+ return $this->yyTokenName[$tokenType];
+ } else {
+ return 'Unknown';
+ }
+ }
+
+ public static function yy_destructor($yymajor, $yypminor)
+ {
+ switch ($yymajor) {
+ default: break; /* If no destructor action specified: do nothing */
+ }
+ }
+
+ public function yy_pop_parser_stack()
+ {
+ if (empty($this->yystack)) {
+ return;
+ }
+ $yytos = array_pop($this->yystack);
+ if ($this->yyTraceFILE && $this->yyidx >= 0) {
+ fwrite($this->yyTraceFILE,
+ $this->yyTracePrompt . 'Popping ' . $this->yyTokenName[$yytos->major] .
+ "\n");
+ }
+ $yymajor = $yytos->major;
+ self::yy_destructor($yymajor, $yytos->minor);
+ $this->yyidx--;
+
+ return $yymajor;
+ }
+
+ public function __destruct()
+ {
+ while ($this->yystack !== Array()) {
+ $this->yy_pop_parser_stack();
+ }
+ if (is_resource($this->yyTraceFILE)) {
+ fclose($this->yyTraceFILE);
+ }
+ }
+
+ public function yy_get_expected_tokens($token)
+ {
+ static $res3 = array();
+ static $res4 = array();
+ $state = $this->yystack[$this->yyidx]->stateno;
+ $expected = self::$yyExpectedTokens[$state];
+ if (isset($res3[$state][$token])) {
+ if ($res3[$state][$token]) {
+ return $expected;
+ }
+ } else {
+ if ($res3[$state][$token] = in_array($token, self::$yyExpectedTokens[$state], true)) {
+ return $expected;
+ }
+ }
+ $stack = $this->yystack;
+ $yyidx = $this->yyidx;
+ do {
+ $yyact = $this->yy_find_shift_action($token);
+ if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
+ // reduce action
+ $done = 0;
+ do {
+ if ($done++ === 100) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // too much recursion prevents proper detection
+ // so give up
+ return array_unique($expected);
+ }
+ $yyruleno = $yyact - self::YYNSTATE;
+ $this->yyidx -= self::$yyRuleInfo[$yyruleno][1];
+ $nextstate = $this->yy_find_reduce_action(
+ $this->yystack[$this->yyidx]->stateno,
+ self::$yyRuleInfo[$yyruleno][0]);
+ if (isset(self::$yyExpectedTokens[$nextstate])) {
+ $expected = array_merge($expected, self::$yyExpectedTokens[$nextstate]);
+ if (isset($res4[$nextstate][$token])) {
+ if ($res4[$nextstate][$token]) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return array_unique($expected);
+ }
+ } else {
+ if ($res4[$nextstate][$token] = in_array($token, self::$yyExpectedTokens[$nextstate], true)) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return array_unique($expected);
+ }
+ }
+ }
+ if ($nextstate < self::YYNSTATE) {
+ // we need to shift a non-terminal
+ $this->yyidx++;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = $nextstate;
+ $x->major = self::$yyRuleInfo[$yyruleno][0];
+ $this->yystack[$this->yyidx] = $x;
+ continue 2;
+ } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // the last token was just ignored, we can't accept
+ // by ignoring input, this is in essence ignoring a
+ // syntax error!
+ return array_unique($expected);
+ } elseif ($nextstate === self::YY_NO_ACTION) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // input accepted, but not shifted (I guess)
+ return $expected;
+ } else {
+ $yyact = $nextstate;
+ }
+ } while (true);
+ }
+ break;
+ } while (true);
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+
+ return array_unique($expected);
+ }
+
+ public function yy_is_expected_token($token)
+ {
+ static $res = array();
+ static $res2 = array();
+ if ($token === 0) {
+ return true; // 0 is not part of this
+ }
+ $state = $this->yystack[$this->yyidx]->stateno;
+ if (isset($res[$state][$token])) {
+ if ($res[$state][$token]) {
+ return true;
+ }
+ } else {
+ if ($res[$state][$token] = in_array($token, self::$yyExpectedTokens[$state], true)) {
+ return true;
+ }
+ }
+ $stack = $this->yystack;
+ $yyidx = $this->yyidx;
+ do {
+ $yyact = $this->yy_find_shift_action($token);
+ if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) {
+ // reduce action
+ $done = 0;
+ do {
+ if ($done++ === 100) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // too much recursion prevents proper detection
+ // so give up
+ return true;
+ }
+ $yyruleno = $yyact - self::YYNSTATE;
+ $this->yyidx -= self::$yyRuleInfo[$yyruleno][1];
+ $nextstate = $this->yy_find_reduce_action(
+ $this->yystack[$this->yyidx]->stateno,
+ self::$yyRuleInfo[$yyruleno][0]);
+ if (isset($res2[$nextstate][$token])) {
+ if ($res2[$nextstate][$token]) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return true;
+ }
+ } else {
+ if ($res2[$nextstate][$token] = (isset(self::$yyExpectedTokens[$nextstate]) && in_array($token, self::$yyExpectedTokens[$nextstate], true))) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ return true;
+ }
+ }
+ if ($nextstate < self::YYNSTATE) {
+ // we need to shift a non-terminal
+ $this->yyidx++;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = $nextstate;
+ $x->major = self::$yyRuleInfo[$yyruleno][0];
+ $this->yystack[$this->yyidx] = $x;
+ continue 2;
+ } elseif ($nextstate === self::YYNSTATE + self::YYNRULE + 1) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ if (!$token) {
+ // end of input: this is valid
+ return true;
+ }
+ // the last token was just ignored, we can't accept
+ // by ignoring input, this is in essence ignoring a
+ // syntax error!
+ return false;
+ } elseif ($nextstate === self::YY_NO_ACTION) {
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+ // input accepted, but not shifted (I guess)
+ return true;
+ } else {
+ $yyact = $nextstate;
+ }
+ } while (true);
+ }
+ break;
+ } while (true);
+ $this->yyidx = $yyidx;
+ $this->yystack = $stack;
+
+ return true;
+ }
+
+ public function yy_find_shift_action($iLookAhead)
+ {
+ $stateno = $this->yystack[$this->yyidx]->stateno;
+
+ /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */
+ if (!isset(self::$yy_shift_ofst[$stateno])) {
+ // no shift actions
+ return self::$yy_default[$stateno];
+ }
+ $i = self::$yy_shift_ofst[$stateno];
+ if ($i === self::YY_SHIFT_USE_DFLT) {
+ return self::$yy_default[$stateno];
+ }
+ if ($iLookAhead === self::YYNOCODE) {
+ return self::YY_NO_ACTION;
+ }
+ $i += $iLookAhead;
+ if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
+ self::$yy_lookahead[$i] != $iLookAhead) {
+ if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback)
+ && ($iFallback = self::$yyFallback[$iLookAhead]) != 0) {
+ if ($this->yyTraceFILE) {
+ fwrite($this->yyTraceFILE, $this->yyTracePrompt . 'FALLBACK ' .
+ $this->yyTokenName[$iLookAhead] . ' => ' .
+ $this->yyTokenName[$iFallback] . "\n");
+ }
+
+ return $this->yy_find_shift_action($iFallback);
+ }
+
+ return self::$yy_default[$stateno];
+ } else {
+ return self::$yy_action[$i];
+ }
+ }
+
+ public function yy_find_reduce_action($stateno, $iLookAhead)
+ {
+ /* $stateno = $this->yystack[$this->yyidx]->stateno; */
+
+ if (!isset(self::$yy_reduce_ofst[$stateno])) {
+ return self::$yy_default[$stateno];
+ }
+ $i = self::$yy_reduce_ofst[$stateno];
+ if ($i === self::YY_REDUCE_USE_DFLT) {
+ return self::$yy_default[$stateno];
+ }
+ if ($iLookAhead === self::YYNOCODE) {
+ return self::YY_NO_ACTION;
+ }
+ $i += $iLookAhead;
+ if ($i < 0 || $i >= self::YY_SZ_ACTTAB ||
+ self::$yy_lookahead[$i] != $iLookAhead) {
+ return self::$yy_default[$stateno];
+ } else {
+ return self::$yy_action[$i];
+ }
+ }
+
+ public function yy_shift($yyNewState, $yyMajor, $yypMinor)
+ {
+ $this->yyidx++;
+ if ($this->yyidx >= self::YYSTACKDEPTH) {
+ $this->yyidx--;
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sStack Overflow!\n", $this->yyTracePrompt);
+ }
+ while ($this->yyidx >= 0) {
+ $this->yy_pop_parser_stack();
+ }
+// line 232 "src/Parser/TemplateParser.y"
+
+ $this->internalError = true;
+ $this->compiler->trigger_template_error('Stack overflow in template parser');
+
+ return;
+ }
+ $yytos = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $yytos->stateno = $yyNewState;
+ $yytos->major = $yyMajor;
+ $yytos->minor = $yypMinor;
+ $this->yystack[] = $yytos;
+ if ($this->yyTraceFILE && $this->yyidx > 0) {
+ fprintf($this->yyTraceFILE, "%sShift %d\n", $this->yyTracePrompt,
+ $yyNewState);
+ fprintf($this->yyTraceFILE, "%sStack:", $this->yyTracePrompt);
+ for ($i = 1; $i <= $this->yyidx; $i++) {
+ fprintf($this->yyTraceFILE, " %s",
+ $this->yyTokenName[$this->yystack[$i]->major]);
+ }
+ fwrite($this->yyTraceFILE,"\n");
+ }
+ }
+
+ public static $yyRuleInfo = array(
+ array( 0 => 61, 1 => 1 ),
+ array( 0 => 62, 1 => 2 ),
+ array( 0 => 62, 1 => 2 ),
+ array( 0 => 62, 1 => 2 ),
+ array( 0 => 62, 1 => 4 ),
+ array( 0 => 63, 1 => 4 ),
+ array( 0 => 63, 1 => 1 ),
+ array( 0 => 64, 1 => 2 ),
+ array( 0 => 64, 1 => 0 ),
+ array( 0 => 62, 1 => 2 ),
+ array( 0 => 62, 1 => 0 ),
+ array( 0 => 65, 1 => 1 ),
+ array( 0 => 65, 1 => 1 ),
+ array( 0 => 65, 1 => 1 ),
+ array( 0 => 65, 1 => 3 ),
+ array( 0 => 65, 1 => 2 ),
+ array( 0 => 66, 1 => 1 ),
+ array( 0 => 66, 1 => 2 ),
+ array( 0 => 66, 1 => 2 ),
+ array( 0 => 69, 1 => 2 ),
+ array( 0 => 68, 1 => 2 ),
+ array( 0 => 71, 1 => 1 ),
+ array( 0 => 71, 1 => 1 ),
+ array( 0 => 71, 1 => 1 ),
+ array( 0 => 67, 1 => 3 ),
+ array( 0 => 67, 1 => 2 ),
+ array( 0 => 67, 1 => 4 ),
+ array( 0 => 67, 1 => 5 ),
+ array( 0 => 67, 1 => 6 ),
+ array( 0 => 67, 1 => 2 ),
+ array( 0 => 67, 1 => 3 ),
+ array( 0 => 67, 1 => 2 ),
+ array( 0 => 67, 1 => 3 ),
+ array( 0 => 67, 1 => 8 ),
+ array( 0 => 79, 1 => 2 ),
+ array( 0 => 79, 1 => 1 ),
+ array( 0 => 67, 1 => 5 ),
+ array( 0 => 67, 1 => 7 ),
+ array( 0 => 67, 1 => 6 ),
+ array( 0 => 67, 1 => 8 ),
+ array( 0 => 67, 1 => 2 ),
+ array( 0 => 67, 1 => 3 ),
+ array( 0 => 67, 1 => 4 ),
+ array( 0 => 65, 1 => 1 ),
+ array( 0 => 67, 1 => 2 ),
+ array( 0 => 67, 1 => 3 ),
+ array( 0 => 67, 1 => 4 ),
+ array( 0 => 67, 1 => 5 ),
+ array( 0 => 72, 1 => 2 ),
+ array( 0 => 72, 1 => 1 ),
+ array( 0 => 72, 1 => 0 ),
+ array( 0 => 82, 1 => 4 ),
+ array( 0 => 82, 1 => 2 ),
+ array( 0 => 82, 1 => 2 ),
+ array( 0 => 82, 1 => 2 ),
+ array( 0 => 82, 1 => 2 ),
+ array( 0 => 82, 1 => 2 ),
+ array( 0 => 82, 1 => 4 ),
+ array( 0 => 78, 1 => 1 ),
+ array( 0 => 78, 1 => 3 ),
+ array( 0 => 77, 1 => 3 ),
+ array( 0 => 77, 1 => 3 ),
+ array( 0 => 77, 1 => 3 ),
+ array( 0 => 77, 1 => 3 ),
+ array( 0 => 75, 1 => 1 ),
+ array( 0 => 75, 1 => 1 ),
+ array( 0 => 75, 1 => 1 ),
+ array( 0 => 75, 1 => 2 ),
+ array( 0 => 75, 1 => 2 ),
+ array( 0 => 75, 1 => 3 ),
+ array( 0 => 75, 1 => 3 ),
+ array( 0 => 75, 1 => 3 ),
+ array( 0 => 75, 1 => 3 ),
+ array( 0 => 75, 1 => 3 ),
+ array( 0 => 75, 1 => 2 ),
+ array( 0 => 88, 1 => 1 ),
+ array( 0 => 75, 1 => 3 ),
+ array( 0 => 75, 1 => 3 ),
+ array( 0 => 83, 1 => 4 ),
+ array( 0 => 84, 1 => 5 ),
+ array( 0 => 84, 1 => 5 ),
+ array( 0 => 84, 1 => 5 ),
+ array( 0 => 84, 1 => 4 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 2 ),
+ array( 0 => 74, 1 => 2 ),
+ array( 0 => 74, 1 => 2 ),
+ array( 0 => 74, 1 => 2 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 3 ),
+ array( 0 => 74, 1 => 2 ),
+ array( 0 => 74, 1 => 2 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 3 ),
+ array( 0 => 74, 1 => 3 ),
+ array( 0 => 74, 1 => 3 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 3 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 2 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 1 ),
+ array( 0 => 74, 1 => 3 ),
+ array( 0 => 91, 1 => 1 ),
+ array( 0 => 91, 1 => 1 ),
+ array( 0 => 73, 1 => 1 ),
+ array( 0 => 73, 1 => 1 ),
+ array( 0 => 73, 1 => 3 ),
+ array( 0 => 73, 1 => 1 ),
+ array( 0 => 73, 1 => 3 ),
+ array( 0 => 73, 1 => 4 ),
+ array( 0 => 73, 1 => 3 ),
+ array( 0 => 73, 1 => 4 ),
+ array( 0 => 70, 1 => 2 ),
+ array( 0 => 70, 1 => 2 ),
+ array( 0 => 96, 1 => 2 ),
+ array( 0 => 96, 1 => 0 ),
+ array( 0 => 97, 1 => 2 ),
+ array( 0 => 97, 1 => 2 ),
+ array( 0 => 97, 1 => 4 ),
+ array( 0 => 97, 1 => 2 ),
+ array( 0 => 97, 1 => 2 ),
+ array( 0 => 97, 1 => 4 ),
+ array( 0 => 97, 1 => 3 ),
+ array( 0 => 97, 1 => 5 ),
+ array( 0 => 97, 1 => 3 ),
+ array( 0 => 97, 1 => 3 ),
+ array( 0 => 97, 1 => 3 ),
+ array( 0 => 97, 1 => 3 ),
+ array( 0 => 97, 1 => 3 ),
+ array( 0 => 97, 1 => 3 ),
+ array( 0 => 97, 1 => 2 ),
+ array( 0 => 80, 1 => 1 ),
+ array( 0 => 80, 1 => 1 ),
+ array( 0 => 80, 1 => 2 ),
+ array( 0 => 98, 1 => 1 ),
+ array( 0 => 98, 1 => 1 ),
+ array( 0 => 98, 1 => 3 ),
+ array( 0 => 95, 1 => 2 ),
+ array( 0 => 99, 1 => 1 ),
+ array( 0 => 99, 1 => 2 ),
+ array( 0 => 100, 1 => 3 ),
+ array( 0 => 100, 1 => 3 ),
+ array( 0 => 100, 1 => 5 ),
+ array( 0 => 100, 1 => 6 ),
+ array( 0 => 100, 1 => 2 ),
+ array( 0 => 90, 1 => 4 ),
+ array( 0 => 101, 1 => 4 ),
+ array( 0 => 101, 1 => 4 ),
+ array( 0 => 102, 1 => 3 ),
+ array( 0 => 102, 1 => 1 ),
+ array( 0 => 102, 1 => 0 ),
+ array( 0 => 76, 1 => 3 ),
+ array( 0 => 76, 1 => 2 ),
+ array( 0 => 103, 1 => 3 ),
+ array( 0 => 103, 1 => 2 ),
+ array( 0 => 81, 1 => 2 ),
+ array( 0 => 81, 1 => 0 ),
+ array( 0 => 104, 1 => 2 ),
+ array( 0 => 104, 1 => 3 ),
+ array( 0 => 104, 1 => 2 ),
+ array( 0 => 93, 1 => 1 ),
+ array( 0 => 93, 1 => 2 ),
+ array( 0 => 93, 1 => 1 ),
+ array( 0 => 93, 1 => 2 ),
+ array( 0 => 93, 1 => 3 ),
+ array( 0 => 86, 1 => 1 ),
+ array( 0 => 86, 1 => 1 ),
+ array( 0 => 85, 1 => 1 ),
+ array( 0 => 87, 1 => 1 ),
+ array( 0 => 94, 1 => 3 ),
+ array( 0 => 94, 1 => 3 ),
+ array( 0 => 105, 1 => 1 ),
+ array( 0 => 105, 1 => 3 ),
+ array( 0 => 105, 1 => 0 ),
+ array( 0 => 106, 1 => 3 ),
+ array( 0 => 106, 1 => 3 ),
+ array( 0 => 106, 1 => 1 ),
+ array( 0 => 92, 1 => 2 ),
+ array( 0 => 92, 1 => 3 ),
+ array( 0 => 107, 1 => 2 ),
+ array( 0 => 107, 1 => 1 ),
+ array( 0 => 108, 1 => 3 ),
+ array( 0 => 108, 1 => 3 ),
+ array( 0 => 108, 1 => 1 ),
+ array( 0 => 108, 1 => 3 ),
+ array( 0 => 108, 1 => 3 ),
+ array( 0 => 108, 1 => 1 ),
+ array( 0 => 108, 1 => 1 ),
+ );
+
+ public static $yyReduceMap = array(
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => 4,
+ 5 => 5,
+ 6 => 6,
+ 21 => 6,
+ 22 => 6,
+ 23 => 6,
+ 35 => 6,
+ 55 => 6,
+ 56 => 6,
+ 64 => 6,
+ 65 => 6,
+ 66 => 6,
+ 83 => 6,
+ 88 => 6,
+ 89 => 6,
+ 94 => 6,
+ 98 => 6,
+ 99 => 6,
+ 103 => 6,
+ 104 => 6,
+ 106 => 6,
+ 111 => 6,
+ 175 => 6,
+ 180 => 6,
+ 7 => 7,
+ 8 => 8,
+ 9 => 9,
+ 11 => 11,
+ 12 => 12,
+ 13 => 13,
+ 14 => 14,
+ 15 => 15,
+ 16 => 16,
+ 17 => 17,
+ 18 => 18,
+ 19 => 19,
+ 20 => 20,
+ 24 => 24,
+ 25 => 25,
+ 26 => 26,
+ 27 => 27,
+ 28 => 28,
+ 29 => 29,
+ 30 => 30,
+ 32 => 30,
+ 31 => 31,
+ 33 => 33,
+ 34 => 34,
+ 36 => 36,
+ 37 => 37,
+ 38 => 38,
+ 39 => 39,
+ 40 => 40,
+ 41 => 41,
+ 42 => 42,
+ 43 => 43,
+ 44 => 44,
+ 45 => 45,
+ 46 => 46,
+ 47 => 47,
+ 48 => 48,
+ 49 => 49,
+ 58 => 49,
+ 153 => 49,
+ 157 => 49,
+ 161 => 49,
+ 163 => 49,
+ 50 => 50,
+ 154 => 50,
+ 160 => 50,
+ 51 => 51,
+ 52 => 52,
+ 53 => 52,
+ 54 => 54,
+ 138 => 54,
+ 57 => 57,
+ 59 => 59,
+ 60 => 60,
+ 61 => 60,
+ 62 => 62,
+ 63 => 63,
+ 67 => 67,
+ 68 => 68,
+ 69 => 69,
+ 70 => 70,
+ 71 => 70,
+ 72 => 72,
+ 73 => 73,
+ 74 => 74,
+ 75 => 75,
+ 76 => 76,
+ 77 => 77,
+ 78 => 78,
+ 79 => 79,
+ 80 => 80,
+ 81 => 80,
+ 82 => 82,
+ 84 => 84,
+ 86 => 84,
+ 87 => 84,
+ 118 => 84,
+ 85 => 85,
+ 90 => 90,
+ 91 => 91,
+ 92 => 92,
+ 93 => 93,
+ 95 => 95,
+ 96 => 96,
+ 97 => 96,
+ 100 => 100,
+ 101 => 101,
+ 102 => 102,
+ 105 => 105,
+ 107 => 107,
+ 108 => 108,
+ 109 => 109,
+ 110 => 110,
+ 112 => 112,
+ 113 => 113,
+ 114 => 114,
+ 115 => 115,
+ 116 => 116,
+ 117 => 117,
+ 119 => 119,
+ 177 => 119,
+ 120 => 120,
+ 121 => 121,
+ 122 => 122,
+ 123 => 123,
+ 124 => 124,
+ 125 => 125,
+ 133 => 125,
+ 126 => 126,
+ 127 => 127,
+ 128 => 128,
+ 129 => 128,
+ 131 => 128,
+ 132 => 128,
+ 130 => 130,
+ 134 => 134,
+ 135 => 135,
+ 136 => 136,
+ 181 => 136,
+ 137 => 137,
+ 139 => 139,
+ 140 => 140,
+ 141 => 141,
+ 142 => 142,
+ 143 => 143,
+ 144 => 144,
+ 145 => 145,
+ 146 => 146,
+ 147 => 147,
+ 148 => 148,
+ 149 => 149,
+ 150 => 150,
+ 151 => 151,
+ 152 => 152,
+ 155 => 155,
+ 156 => 156,
+ 158 => 158,
+ 159 => 159,
+ 162 => 162,
+ 164 => 164,
+ 165 => 165,
+ 166 => 166,
+ 167 => 167,
+ 168 => 168,
+ 169 => 169,
+ 170 => 170,
+ 171 => 171,
+ 172 => 172,
+ 173 => 173,
+ 174 => 173,
+ 176 => 176,
+ 178 => 178,
+ 179 => 179,
+ 182 => 182,
+ 183 => 183,
+ 184 => 184,
+ 185 => 185,
+ 188 => 185,
+ 186 => 186,
+ 189 => 186,
+ 187 => 187,
+ 190 => 190,
+ 191 => 191,
+ );
+// line 245 "src/Parser/TemplateParser.y"
+ public function yy_r0(){
+ $this->root_buffer->prepend_array($this, $this->template_prefix);
+ $this->root_buffer->append_array($this, $this->template_postfix);
+ $this->_retvalue = $this->root_buffer->to_smarty_php($this);
+ }
+// line 252 "src/Parser/TemplateParser.y"
+ public function yy_r1(){
+ $text = $this->yystack[ $this->yyidx + 0 ]->minor;
+
+ if ((string)$text == '') {
+ $this->current_buffer->append_subtree($this, null);
+ }
+
+ $this->current_buffer->append_subtree($this, new \Smarty\ParseTree\Text($text, $this->strip));
+ }
+// line 262 "src/Parser/TemplateParser.y"
+ public function yy_r2(){
+ $this->strip = true;
+ }
+// line 266 "src/Parser/TemplateParser.y"
+ public function yy_r3(){
+ $this->strip = false;
+ }
+// line 271 "src/Parser/TemplateParser.y"
+ public function yy_r4(){
+ $this->current_buffer->append_subtree($this, new \Smarty\ParseTree\Text($this->yystack[$this->yyidx + -1]->minor));
+ }
+// line 276 "src/Parser/TemplateParser.y"
+ public function yy_r5(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor.$this->yystack[$this->yyidx + -1]->minor;
+ }
+// line 279 "src/Parser/TemplateParser.y"
+ public function yy_r6(){
+ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 283 "src/Parser/TemplateParser.y"
+ public function yy_r7(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor;
+
+ }
+// line 288 "src/Parser/TemplateParser.y"
+ public function yy_r8(){
+ $this->_retvalue = '';
+ }
+// line 292 "src/Parser/TemplateParser.y"
+ public function yy_r9(){
+ $this->current_buffer->append_subtree($this, $this->mergePrefixCode($this->yystack[$this->yyidx + 0]->minor));
+ $this->compiler->has_variable_string = false;
+ $this->block_nesting_level = $this->compiler->getTagStackCount();
+ }
+// line 302 "src/Parser/TemplateParser.y"
+ public function yy_r11(){
+ $var = trim(substr($this->yystack[$this->yyidx + 0]->minor, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $');
+ $attributes = [];
+ if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) {
+ $attributes[] = 'nocache';
+ $var = $match[1];
+ }
+ $this->_retvalue = $this->compiler->compilePrintExpression($this->compiler->compileVariable('\''.$var.'\''), $attributes);
+ }
+// line 313 "src/Parser/TemplateParser.y"
+ public function yy_r12(){
+ $tag = trim(substr($this->yystack[$this->yyidx + 0]->minor, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()));
+ if ($tag == 'strip') {
+ $this->strip = true;
+ $this->_retvalue = null;
+ } else {
+ if (defined($tag)) {
+ if ($this->security) {
+ $this->security->isTrustedConstant($tag, $this->compiler);
+ }
+ $this->_retvalue = $this->compiler->compilePrintExpression($tag);
+ } else {
+ if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) {
+ $this->_retvalue = $this->compiler->compileTag($match[1],array('\'nocache\''));
+ } else {
+ $this->_retvalue = $this->compiler->compileTag($tag,array());
+ }
+ }
+ }
+ }
+// line 334 "src/Parser/TemplateParser.y"
+ public function yy_r13(){
+ $j = strrpos($this->yystack[$this->yyidx + 0]->minor,'.');
+ if ($this->yystack[$this->yyidx + 0]->minor[$j+1] == 'c') {
+ // {$smarty.block.child}
+ $this->_retvalue = $this->compiler->compileChildBlock();
+ } else {
+ // {$smarty.block.parent}
+ $this->_retvalue = $this->compiler->compileParentBlock();
+ }
+ }
+// line 345 "src/Parser/TemplateParser.y"
+ public function yy_r14(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
+ }
+// line 349 "src/Parser/TemplateParser.y"
+ public function yy_r15(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
+ }
+// line 353 "src/Parser/TemplateParser.y"
+ public function yy_r16(){
+ $this->_retvalue = $this->compiler->compilePrintExpression($this->yystack[$this->yyidx + 0]->minor[0], $this->yystack[$this->yyidx + 0]->minor[1]);
+ }
+// line 362 "src/Parser/TemplateParser.y"
+ public function yy_r17(){
+ $this->_retvalue = $this->compiler->compileTag('assign',array_merge(array(array('value'=>$this->yystack[$this->yyidx + 0]->minor[0]),array('var'=>'\''.substr($this->yystack[$this->yyidx + -1]->minor,1).'\'')),$this->yystack[$this->yyidx + 0]->minor[1]));
+ }
+// line 366 "src/Parser/TemplateParser.y"
+ public function yy_r18(){
+ $this->_retvalue = $this->compiler->compileTag('assign',array_merge(array(array('value'=>$this->yystack[$this->yyidx + 0]->minor[0]),array('var'=>$this->yystack[$this->yyidx + -1]->minor['var'])),$this->yystack[$this->yyidx + 0]->minor[1]),array('smarty_internal_index'=>$this->yystack[$this->yyidx + -1]->minor['smarty_internal_index']));
+ }
+// line 370 "src/Parser/TemplateParser.y"
+ public function yy_r19(){
+ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 374 "src/Parser/TemplateParser.y"
+ public function yy_r20(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 389 "src/Parser/TemplateParser.y"
+ public function yy_r24(){
+ if (defined($this->yystack[$this->yyidx + -1]->minor)) {
+ if ($this->security) {
+ $this->security->isTrustedConstant($this->yystack[$this->yyidx + -1]->minor, $this->compiler);
+ }
+ $this->_retvalue = $this->compiler->compilePrintExpression($this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor);
+ } else {
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor);
+ }
+ }
+// line 399 "src/Parser/TemplateParser.y"
+ public function yy_r25(){
+ if (defined($this->yystack[$this->yyidx + 0]->minor)) {
+ if ($this->security) {
+ $this->security->isTrustedConstant($this->yystack[$this->yyidx + 0]->minor, $this->compiler);
+ }
+ $this->_retvalue = $this->compiler->compilePrintExpression($this->yystack[$this->yyidx + 0]->minor);
+ } else {
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + 0]->minor,array());
+ }
+ }
+// line 412 "src/Parser/TemplateParser.y"
+ public function yy_r26(){
+ if (defined($this->yystack[$this->yyidx + -2]->minor)) {
+ if ($this->security) {
+ $this->security->isTrustedConstant($this->yystack[$this->yyidx + -2]->minor, $this->compiler);
+ }
+ $this->_retvalue = $this->compiler->compilePrintExpression($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor);
+ } else {
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -2]->minor,$this->yystack[$this->yyidx + 0]->minor, array('modifierlist'=>$this->yystack[$this->yyidx + -1]->minor));
+ }
+ }
+// line 424 "src/Parser/TemplateParser.y"
+ public function yy_r27(){
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -3]->minor,$this->yystack[$this->yyidx + 0]->minor,array('object_method'=>$this->yystack[$this->yyidx + -1]->minor));
+ }
+// line 429 "src/Parser/TemplateParser.y"
+ public function yy_r28(){
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -4]->minor,$this->yystack[$this->yyidx + 0]->minor,array('modifierlist'=>$this->yystack[$this->yyidx + -1]->minor, 'object_method'=>$this->yystack[$this->yyidx + -2]->minor));
+ }
+// line 434 "src/Parser/TemplateParser.y"
+ public function yy_r29(){
+ $tag = trim(substr($this->yystack[$this->yyidx + -1]->minor,$this->compiler->getLdelLength()));
+ $this->_retvalue = $this->compiler->compileTag(($tag === 'else if')? 'elseif' : $tag,array(),array('if condition'=>$this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 439 "src/Parser/TemplateParser.y"
+ public function yy_r30(){
+ $tag = trim(substr($this->yystack[$this->yyidx + -2]->minor,$this->compiler->getLdelLength()));
+ $this->_retvalue = $this->compiler->compileTag(($tag === 'else if')? 'elseif' : $tag,$this->yystack[$this->yyidx + 0]->minor,array('if condition'=>$this->yystack[$this->yyidx + -1]->minor));
+ }
+// line 444 "src/Parser/TemplateParser.y"
+ public function yy_r31(){
+ $tag = trim(substr($this->yystack[$this->yyidx + -1]->minor,$this->compiler->getLdelLength()));
+ $this->_retvalue = $this->compiler->compileTag(($tag === 'else if')? 'elseif' : $tag,array(),array('if condition'=>$this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 455 "src/Parser/TemplateParser.y"
+ public function yy_r33(){
+ $this->_retvalue = $this->compiler->compileTag('for',array_merge($this->yystack[$this->yyidx + 0]->minor,array(array('start'=>$this->yystack[$this->yyidx + -6]->minor),array('ifexp'=>$this->yystack[$this->yyidx + -4]->minor),array('var'=>$this->yystack[$this->yyidx + -2]->minor),array('step'=>$this->yystack[$this->yyidx + -1]->minor))),1);
+ }
+// line 459 "src/Parser/TemplateParser.y"
+ public function yy_r34(){
+ $this->_retvalue = '='.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 467 "src/Parser/TemplateParser.y"
+ public function yy_r36(){
+ $this->_retvalue = $this->compiler->compileTag('for',array_merge($this->yystack[$this->yyidx + 0]->minor,array(array('start'=>$this->yystack[$this->yyidx + -3]->minor),array('to'=>$this->yystack[$this->yyidx + -1]->minor))),0);
+ }
+// line 471 "src/Parser/TemplateParser.y"
+ public function yy_r37(){
+ $this->_retvalue = $this->compiler->compileTag('for',array_merge($this->yystack[$this->yyidx + 0]->minor,array(array('start'=>$this->yystack[$this->yyidx + -5]->minor),array('to'=>$this->yystack[$this->yyidx + -3]->minor),array('step'=>$this->yystack[$this->yyidx + -1]->minor))),0);
+ }
+// line 476 "src/Parser/TemplateParser.y"
+ public function yy_r38(){
+ $this->_retvalue = $this->compiler->compileTag('foreach',array_merge($this->yystack[$this->yyidx + 0]->minor,array(array('from'=>$this->yystack[$this->yyidx + -3]->minor),array('item'=>$this->yystack[$this->yyidx + -1]->minor))));
+ }
+// line 480 "src/Parser/TemplateParser.y"
+ public function yy_r39(){
+ $this->_retvalue = $this->compiler->compileTag('foreach',array_merge($this->yystack[$this->yyidx + 0]->minor,array(array('from'=>$this->yystack[$this->yyidx + -5]->minor),array('item'=>$this->yystack[$this->yyidx + -1]->minor),array('key'=>$this->yystack[$this->yyidx + -3]->minor))));
+ }
+// line 483 "src/Parser/TemplateParser.y"
+ public function yy_r40(){
+ $this->_retvalue = $this->compiler->compileTag('foreach',$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 488 "src/Parser/TemplateParser.y"
+ public function yy_r41(){
+ $this->_retvalue = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array(array_merge(array($this->yystack[$this->yyidx + -1]->minor),$this->yystack[$this->yyidx + 0]->minor))));
+ }
+// line 492 "src/Parser/TemplateParser.y"
+ public function yy_r42(){
+ $this->_retvalue = $this->compiler->compileTag('setfilter',array(),array('modifier_list'=>array_merge(array(array_merge(array($this->yystack[$this->yyidx + -2]->minor),$this->yystack[$this->yyidx + -1]->minor)),$this->yystack[$this->yyidx + 0]->minor)));
+ }
+// line 498 "src/Parser/TemplateParser.y"
+ public function yy_r43(){
+ $tag = trim(substr($this->yystack[$this->yyidx + 0]->minor, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' /');
+ if ($tag === 'strip') {
+ $this->strip = false;
+ $this->_retvalue = null;
+ } else {
+ $this->_retvalue = $this->compiler->compileTag($tag.'close',array());
+ }
+ }
+// line 507 "src/Parser/TemplateParser.y"
+ public function yy_r44(){
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + 0]->minor.'close',array());
+ }
+// line 511 "src/Parser/TemplateParser.y"
+ public function yy_r45(){
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -1]->minor.'close',array(),array('modifier_list'=>$this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 516 "src/Parser/TemplateParser.y"
+ public function yy_r46(){
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -2]->minor.'close',array(),array('object_method'=>$this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 520 "src/Parser/TemplateParser.y"
+ public function yy_r47(){
+ $this->_retvalue = $this->compiler->compileTag($this->yystack[$this->yyidx + -3]->minor.'close',array(),array('object_method'=>$this->yystack[$this->yyidx + -1]->minor, 'modifier_list'=>$this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 528 "src/Parser/TemplateParser.y"
+ public function yy_r48(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
+ $this->_retvalue[] = $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 534 "src/Parser/TemplateParser.y"
+ public function yy_r49(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 539 "src/Parser/TemplateParser.y"
+ public function yy_r50(){
+ $this->_retvalue = array();
+ }
+// line 544 "src/Parser/TemplateParser.y"
+ public function yy_r51(){
+ if (defined($this->yystack[$this->yyidx + 0]->minor)) {
+ if ($this->security) {
+ $this->security->isTrustedConstant($this->yystack[$this->yyidx + 0]->minor, $this->compiler);
+ }
+ $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>$this->yystack[$this->yyidx + 0]->minor);
+ } else {
+ $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>'\''.$this->yystack[$this->yyidx + 0]->minor.'\'');
+ }
+ }
+// line 555 "src/Parser/TemplateParser.y"
+ public function yy_r52(){
+ $this->_retvalue = array(trim($this->yystack[$this->yyidx + -1]->minor," =\n\r\t")=>$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 563 "src/Parser/TemplateParser.y"
+ public function yy_r54(){
+ $this->_retvalue = '\''.$this->yystack[$this->yyidx + 0]->minor.'\'';
+ }
+// line 575 "src/Parser/TemplateParser.y"
+ public function yy_r57(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor=>$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 588 "src/Parser/TemplateParser.y"
+ public function yy_r59(){
+ $this->yystack[$this->yyidx + -2]->minor[]=$this->yystack[$this->yyidx + 0]->minor;
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor;
+ }
+// line 593 "src/Parser/TemplateParser.y"
+ public function yy_r60(){
+ $this->_retvalue = array('var' => '\''.substr($this->yystack[$this->yyidx + -2]->minor,1).'\'', 'value'=>$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 600 "src/Parser/TemplateParser.y"
+ public function yy_r62(){
+ $this->_retvalue = array('var' => $this->yystack[$this->yyidx + -2]->minor, 'value'=>$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 604 "src/Parser/TemplateParser.y"
+ public function yy_r63(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
+ }
+// line 629 "src/Parser/TemplateParser.y"
+ public function yy_r67(){
+ $this->_retvalue = '$_smarty_tpl->getVariable(\''. substr($this->yystack[$this->yyidx + 0]->minor,1) .'\')->preIncDec(\'' . $this->yystack[$this->yyidx + -1]->minor . '\')';
+ }
+// line 634 "src/Parser/TemplateParser.y"
+ public function yy_r68(){
+ $this->_retvalue = '$_smarty_tpl->getVariable(\''. substr($this->yystack[$this->yyidx + -1]->minor,1) .'\')->postIncDec(\'' . $this->yystack[$this->yyidx + 0]->minor . '\')';
+ }
+// line 639 "src/Parser/TemplateParser.y"
+ public function yy_r69(){
+ $this->_retvalue = '$_smarty_tpl->getStreamVariable(\''.substr($this->yystack[$this->yyidx + -2]->minor,1).'://' . $this->yystack[$this->yyidx + 0]->minor . '\')';
+ }
+// line 644 "src/Parser/TemplateParser.y"
+ public function yy_r70(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor . trim($this->yystack[$this->yyidx + -1]->minor) . $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 654 "src/Parser/TemplateParser.y"
+ public function yy_r72(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor['pre']. $this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + -1]->minor['op'].$this->yystack[$this->yyidx + 0]->minor .')';
+ }
+// line 658 "src/Parser/TemplateParser.y"
+ public function yy_r73(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 662 "src/Parser/TemplateParser.y"
+ public function yy_r74(){
+ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor . $this->yystack[$this->yyidx + -1]->minor . ')';
+ }
+// line 666 "src/Parser/TemplateParser.y"
+ public function yy_r75(){
+ static $isin = [
+ 'isin' => 'in_array(',
+ 'isnotin' => '!in_array(',
+ ];
+ $op = strtolower(str_replace(' ', '', $this->yystack[$this->yyidx + 0]->minor));
+ $this->_retvalue = $isin[$op];
+ }
+// line 675 "src/Parser/TemplateParser.y"
+ public function yy_r76(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + -2]->minor.','.$this->yystack[$this->yyidx + 0]->minor.')';
+ }
+// line 679 "src/Parser/TemplateParser.y"
+ public function yy_r77(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor . $this->yystack[$this->yyidx + -2]->minor.',(array)'.$this->yystack[$this->yyidx + 0]->minor.')';
+ }
+// line 684 "src/Parser/TemplateParser.y"
+ public function yy_r78(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor.' ?? '.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 691 "src/Parser/TemplateParser.y"
+ public function yy_r79(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -4]->minor.' ? '. $this->compiler->compileVariable('\''.substr($this->yystack[$this->yyidx + -2]->minor,1).'\'') . ' : '.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 695 "src/Parser/TemplateParser.y"
+ public function yy_r80(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -4]->minor.' ? '.$this->yystack[$this->yyidx + -2]->minor.' : '.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 704 "src/Parser/TemplateParser.y"
+ public function yy_r82(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor.' ?: '.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 714 "src/Parser/TemplateParser.y"
+ public function yy_r84(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 719 "src/Parser/TemplateParser.y"
+ public function yy_r85(){
+ $this->_retvalue = '!'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 740 "src/Parser/TemplateParser.y"
+ public function yy_r90(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'.'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 744 "src/Parser/TemplateParser.y"
+ public function yy_r91(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.'.';
+ }
+// line 748 "src/Parser/TemplateParser.y"
+ public function yy_r92(){
+ $this->_retvalue = '.'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 753 "src/Parser/TemplateParser.y"
+ public function yy_r93(){
+ if (defined($this->yystack[$this->yyidx + 0]->minor)) {
+ if ($this->security) {
+ $this->security->isTrustedConstant($this->yystack[$this->yyidx + 0]->minor, $this->compiler);
+ }
+ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
+ } else {
+ $this->_retvalue = '\''.$this->yystack[$this->yyidx + 0]->minor.'\'';
+ }
+ }
+// line 770 "src/Parser/TemplateParser.y"
+ public function yy_r95(){
+ $this->_retvalue = '('. $this->yystack[$this->yyidx + -1]->minor .')';
+ }
+// line 774 "src/Parser/TemplateParser.y"
+ public function yy_r96(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 792 "src/Parser/TemplateParser.y"
+ public function yy_r100(){
+ if ($this->security && $this->security->static_classes !== array()) {
+ $this->compiler->trigger_template_error('dynamic static class not allowed by security setting');
+ }
+ $prefixVar = $this->compiler->getNewPrefixVariable();
+ if ($this->yystack[$this->yyidx + -2]->minor['var'] === '\'smarty\'') {
+ $this->compiler->appendPrefixCode("compile(array(),$this->compiler,$this->yystack[$this->yyidx + -2]->minor['smarty_internal_index']).';?>');
+ } else {
+ $this->compiler->appendPrefixCode("compiler->compileVariable($this->yystack[$this->yyidx + -2]->minor['var']).$this->yystack[$this->yyidx + -2]->minor['smarty_internal_index'].';?>');
+ }
+ $this->_retvalue = $prefixVar .'::'.$this->yystack[$this->yyidx + 0]->minor[0].$this->yystack[$this->yyidx + 0]->minor[1];
+ }
+// line 806 "src/Parser/TemplateParser.y"
+ public function yy_r101(){
+ $prefixVar = $this->compiler->getNewPrefixVariable();
+ $tmp = $this->compiler->appendCode('', (string) $this->yystack[$this->yyidx + 0]->minor);
+ $this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, ""));
+ $this->_retvalue = $prefixVar;
+ }
+// line 813 "src/Parser/TemplateParser.y"
+ public function yy_r102(){
+ $this->_retvalue = $this->compiler->compileModifier($this->yystack[$this->yyidx + 0]->minor, $this->yystack[$this->yyidx + -1]->minor);
+ }
+// line 826 "src/Parser/TemplateParser.y"
+ public function yy_r105(){
+ if (!in_array(strtolower($this->yystack[$this->yyidx + -2]->minor), array('self', 'parent')) && (!$this->security || $this->security->isTrustedStaticClassAccess($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + 0]->minor, $this->compiler))) {
+ if (isset($this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor])) {
+ $this->_retvalue = $this->smarty->registered_classes[$this->yystack[$this->yyidx + -2]->minor].'::'.$this->yystack[$this->yyidx + 0]->minor[0].$this->yystack[$this->yyidx + 0]->minor[1];
+ } else {
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'::'.$this->yystack[$this->yyidx + 0]->minor[0].$this->yystack[$this->yyidx + 0]->minor[1];
+ }
+ } else {
+ $this->compiler->trigger_template_error ('static class \''.$this->yystack[$this->yyidx + -2]->minor.'\' is undefined or not allowed by security setting');
+ }
+ }
+// line 845 "src/Parser/TemplateParser.y"
+ public function yy_r107(){
+ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 856 "src/Parser/TemplateParser.y"
+ public function yy_r108(){
+ $this->_retvalue = $this->compiler->compileVariable('\''.substr($this->yystack[$this->yyidx + 0]->minor,1).'\'');
+ }
+// line 859 "src/Parser/TemplateParser.y"
+ public function yy_r109(){
+ if ($this->yystack[$this->yyidx + 0]->minor['var'] === '\'smarty\'') {
+ $smarty_var = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,$this->yystack[$this->yyidx + 0]->minor['smarty_internal_index']);
+ $this->_retvalue = $smarty_var;
+ } else {
+ // used for array reset,next,prev,end,current
+ $this->last_variable = $this->yystack[$this->yyidx + 0]->minor['var'];
+ $this->last_index = $this->yystack[$this->yyidx + 0]->minor['smarty_internal_index'];
+ $this->_retvalue = $this->compiler->compileVariable($this->yystack[$this->yyidx + 0]->minor['var']).$this->yystack[$this->yyidx + 0]->minor['smarty_internal_index'];
+ }
+ }
+// line 872 "src/Parser/TemplateParser.y"
+ public function yy_r110(){
+ $this->_retvalue = '$_smarty_tpl->getVariable('. $this->yystack[$this->yyidx + -2]->minor .')->'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 882 "src/Parser/TemplateParser.y"
+ public function yy_r112(){
+ $this->_retvalue = $this->compiler->compileConfigVariable('\'' . $this->yystack[$this->yyidx + -1]->minor . '\'');
+ }
+// line 886 "src/Parser/TemplateParser.y"
+ public function yy_r113(){
+ $this->_retvalue = '(is_array($tmp = ' . $this->compiler->compileConfigVariable('\'' . $this->yystack[$this->yyidx + -2]->minor . '\'') . ') ? $tmp'.$this->yystack[$this->yyidx + 0]->minor.' :null)';
+ }
+// line 890 "src/Parser/TemplateParser.y"
+ public function yy_r114(){
+ $this->_retvalue = $this->compiler->compileConfigVariable($this->yystack[$this->yyidx + -1]->minor);
+ }
+// line 894 "src/Parser/TemplateParser.y"
+ public function yy_r115(){
+ $this->_retvalue = '(is_array($tmp = ' . $this->compiler->compileConfigVariable($this->yystack[$this->yyidx + -2]->minor) . ') ? $tmp'.$this->yystack[$this->yyidx + 0]->minor.' : null)';
+ }
+// line 898 "src/Parser/TemplateParser.y"
+ public function yy_r116(){
+ $this->_retvalue = array('var'=>'\''.substr($this->yystack[$this->yyidx + -1]->minor,1).'\'', 'smarty_internal_index'=>$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 901 "src/Parser/TemplateParser.y"
+ public function yy_r117(){
+ $this->_retvalue = array('var'=>$this->yystack[$this->yyidx + -1]->minor, 'smarty_internal_index'=>$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 914 "src/Parser/TemplateParser.y"
+ public function yy_r119(){
+ return;
+ }
+// line 920 "src/Parser/TemplateParser.y"
+ public function yy_r120(){
+ $this->_retvalue = '['.$this->compiler->compileVariable('\''.substr($this->yystack[$this->yyidx + 0]->minor,1).'\'').']';
+ }
+// line 923 "src/Parser/TemplateParser.y"
+ public function yy_r121(){
+ $this->_retvalue = '['.$this->compiler->compileVariable($this->yystack[$this->yyidx + 0]->minor).']';
+ }
+// line 927 "src/Parser/TemplateParser.y"
+ public function yy_r122(){
+ $this->_retvalue = '['.$this->compiler->compileVariable($this->yystack[$this->yyidx + -2]->minor).'->'.$this->yystack[$this->yyidx + 0]->minor.']';
+ }
+// line 931 "src/Parser/TemplateParser.y"
+ public function yy_r123(){
+ $this->_retvalue = '[\''. $this->yystack[$this->yyidx + 0]->minor .'\']';
+ }
+// line 935 "src/Parser/TemplateParser.y"
+ public function yy_r124(){
+ $this->_retvalue = '['. $this->yystack[$this->yyidx + 0]->minor .']';
+ }
+// line 940 "src/Parser/TemplateParser.y"
+ public function yy_r125(){
+ $this->_retvalue = '['. $this->yystack[$this->yyidx + -1]->minor .']';
+ }
+// line 945 "src/Parser/TemplateParser.y"
+ public function yy_r126(){
+ $this->_retvalue = '['.(new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,'[\'section\'][\''.$this->yystack[$this->yyidx + -1]->minor.'\'][\'index\']').']';
+ }
+// line 949 "src/Parser/TemplateParser.y"
+ public function yy_r127(){
+ $this->_retvalue = '['.(new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,'[\'section\'][\''.$this->yystack[$this->yyidx + -3]->minor.'\'][\''.$this->yystack[$this->yyidx + -1]->minor.'\']').']';
+ }
+// line 952 "src/Parser/TemplateParser.y"
+ public function yy_r128(){
+ $this->_retvalue = '['.$this->yystack[$this->yyidx + -1]->minor.']';
+ }
+// line 958 "src/Parser/TemplateParser.y"
+ public function yy_r130(){
+ $this->_retvalue = '['.$this->compiler->compileVariable('\''.substr($this->yystack[$this->yyidx + -1]->minor,1).'\'').']';
+ }
+// line 974 "src/Parser/TemplateParser.y"
+ public function yy_r134(){
+ $this->_retvalue = '[]';
+ }
+// line 984 "src/Parser/TemplateParser.y"
+ public function yy_r135(){
+ $this->_retvalue = '\''.substr($this->yystack[$this->yyidx + 0]->minor,1).'\'';
+ }
+// line 988 "src/Parser/TemplateParser.y"
+ public function yy_r136(){
+ $this->_retvalue = '\'\'';
+ }
+// line 993 "src/Parser/TemplateParser.y"
+ public function yy_r137(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.'.'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1001 "src/Parser/TemplateParser.y"
+ public function yy_r139(){
+ $var = trim(substr($this->yystack[$this->yyidx + 0]->minor, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $');
+ $this->_retvalue = $this->compiler->compileVariable('\''.$var.'\'');
+ }
+// line 1007 "src/Parser/TemplateParser.y"
+ public function yy_r140(){
+ $this->_retvalue = '('.$this->yystack[$this->yyidx + -1]->minor.')';
+ }
+// line 1014 "src/Parser/TemplateParser.y"
+ public function yy_r141(){
+ if ($this->yystack[$this->yyidx + -1]->minor['var'] === '\'smarty\'') {
+ $this->_retvalue = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,$this->yystack[$this->yyidx + -1]->minor['smarty_internal_index']).$this->yystack[$this->yyidx + 0]->minor;
+ } else {
+ $this->_retvalue = $this->compiler->compileVariable($this->yystack[$this->yyidx + -1]->minor['var']).$this->yystack[$this->yyidx + -1]->minor['smarty_internal_index'].$this->yystack[$this->yyidx + 0]->minor;
+ }
+ }
+// line 1023 "src/Parser/TemplateParser.y"
+ public function yy_r142(){
+ $this->_retvalue = $this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1028 "src/Parser/TemplateParser.y"
+ public function yy_r143(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1033 "src/Parser/TemplateParser.y"
+ public function yy_r144(){
+ if ($this->security && substr($this->yystack[$this->yyidx + -1]->minor,0,1) === '_') {
+ $this->compiler->trigger_template_error (self::ERR1);
+ }
+ $this->_retvalue = '->'.$this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1040 "src/Parser/TemplateParser.y"
+ public function yy_r145(){
+ if ($this->security) {
+ $this->compiler->trigger_template_error (self::ERR2);
+ }
+ $this->_retvalue = '->{'.$this->compiler->compileVariable($this->yystack[$this->yyidx + -1]->minor).$this->yystack[$this->yyidx + 0]->minor.'}';
+ }
+// line 1047 "src/Parser/TemplateParser.y"
+ public function yy_r146(){
+ if ($this->security) {
+ $this->compiler->trigger_template_error (self::ERR2);
+ }
+ $this->_retvalue = '->{'.$this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + 0]->minor.'}';
+ }
+// line 1054 "src/Parser/TemplateParser.y"
+ public function yy_r147(){
+ if ($this->security) {
+ $this->compiler->trigger_template_error (self::ERR2);
+ }
+ $this->_retvalue = '->{\''.$this->yystack[$this->yyidx + -4]->minor.'\'.'.$this->yystack[$this->yyidx + -2]->minor.$this->yystack[$this->yyidx + 0]->minor.'}';
+ }
+// line 1062 "src/Parser/TemplateParser.y"
+ public function yy_r148(){
+ $this->_retvalue = '->'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1070 "src/Parser/TemplateParser.y"
+ public function yy_r149(){
+ $this->_retvalue = $this->compiler->compileModifierInExpression($this->yystack[$this->yyidx + -3]->minor, $this->yystack[$this->yyidx + -1]->minor);
+ }
+// line 1078 "src/Parser/TemplateParser.y"
+ public function yy_r150(){
+ if ($this->security && substr($this->yystack[$this->yyidx + -3]->minor,0,1) === '_') {
+ $this->compiler->trigger_template_error (self::ERR1);
+ }
+ $this->_retvalue = $this->yystack[$this->yyidx + -3]->minor . '('. implode(',',$this->yystack[$this->yyidx + -1]->minor) .')';
+ }
+// line 1085 "src/Parser/TemplateParser.y"
+ public function yy_r151(){
+ if ($this->security) {
+ $this->compiler->trigger_template_error (self::ERR2);
+ }
+ $prefixVar = $this->compiler->getNewPrefixVariable();
+ $this->compiler->appendPrefixCode("compiler->compileVariable('\''.substr($this->yystack[$this->yyidx + -3]->minor,1).'\'').';?>');
+ $this->_retvalue = $prefixVar .'('. implode(',',$this->yystack[$this->yyidx + -1]->minor) .')';
+ }
+// line 1096 "src/Parser/TemplateParser.y"
+ public function yy_r152(){
+ $this->_retvalue = array_merge($this->yystack[$this->yyidx + -2]->minor,array($this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 1113 "src/Parser/TemplateParser.y"
+ public function yy_r155(){
+ $this->_retvalue = array_merge($this->yystack[$this->yyidx + -2]->minor,array(array_merge($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor)));
+ }
+// line 1117 "src/Parser/TemplateParser.y"
+ public function yy_r156(){
+ $this->_retvalue = array(array_merge($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor));
+ }
+// line 1125 "src/Parser/TemplateParser.y"
+ public function yy_r158(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 1133 "src/Parser/TemplateParser.y"
+ public function yy_r159(){
+ $this->_retvalue = array_merge($this->yystack[$this->yyidx + -1]->minor,$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 1146 "src/Parser/TemplateParser.y"
+ public function yy_r162(){
+ $this->_retvalue = array(trim($this->yystack[$this->yyidx + -1]->minor).$this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 1155 "src/Parser/TemplateParser.y"
+ public function yy_r164(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor, '', 'method');
+ }
+// line 1160 "src/Parser/TemplateParser.y"
+ public function yy_r165(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor, 'method');
+ }
+// line 1165 "src/Parser/TemplateParser.y"
+ public function yy_r166(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor, '');
+ }
+// line 1170 "src/Parser/TemplateParser.y"
+ public function yy_r167(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + -1]->minor, $this->yystack[$this->yyidx + 0]->minor, 'property');
+ }
+// line 1175 "src/Parser/TemplateParser.y"
+ public function yy_r168(){
+ $this->_retvalue = array($this->yystack[$this->yyidx + -2]->minor, $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor, 'property');
+ }
+// line 1181 "src/Parser/TemplateParser.y"
+ public function yy_r169(){
+ $this->_retvalue = ' '. trim($this->yystack[$this->yyidx + 0]->minor) . ' ';
+ }
+// line 1185 "src/Parser/TemplateParser.y"
+ public function yy_r170(){
+ static $lops = array(
+ 'eq' => ' == ',
+ 'ne' => ' != ',
+ 'neq' => ' != ',
+ 'gt' => ' > ',
+ 'ge' => ' >= ',
+ 'gte' => ' >= ',
+ 'lt' => ' < ',
+ 'le' => ' <= ',
+ 'lte' => ' <= ',
+ 'mod' => ' % ',
+ 'and' => ' && ',
+ 'or' => ' || ',
+ 'xor' => ' xor ',
+ );
+ $op = strtolower(preg_replace('/\s*/', '', $this->yystack[$this->yyidx + 0]->minor));
+ $this->_retvalue = $lops[$op];
+ }
+// line 1204 "src/Parser/TemplateParser.y"
+ public function yy_r171(){
+ static $tlops = array(
+ 'isdivby' => array('op' => ' % ', 'pre' => '!('),
+ 'isnotdivby' => array('op' => ' % ', 'pre' => '('),
+ 'isevenby' => array('op' => ' / ', 'pre' => '!(1 & '),
+ 'isnotevenby' => array('op' => ' / ', 'pre' => '(1 & '),
+ 'isoddby' => array('op' => ' / ', 'pre' => '(1 & '),
+ 'isnotoddby' => array('op' => ' / ', 'pre' => '!(1 & '),
+ );
+ $op = strtolower(preg_replace('/\s*/', '', $this->yystack[$this->yyidx + 0]->minor));
+ $this->_retvalue = $tlops[$op];
+ }
+// line 1217 "src/Parser/TemplateParser.y"
+ public function yy_r172(){
+ static $scond = array (
+ 'iseven' => '!(1 & ',
+ 'isnoteven' => '(1 & ',
+ 'isodd' => '(1 & ',
+ 'isnotodd' => '!(1 & ',
+ );
+ $op = strtolower(str_replace(' ', '', $this->yystack[$this->yyidx + 0]->minor));
+ $this->_retvalue = $scond[$op];
+ }
+// line 1231 "src/Parser/TemplateParser.y"
+ public function yy_r173(){
+ $this->_retvalue = 'array('.$this->yystack[$this->yyidx + -1]->minor.')';
+ }
+// line 1242 "src/Parser/TemplateParser.y"
+ public function yy_r176(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.','.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1250 "src/Parser/TemplateParser.y"
+ public function yy_r178(){
+ $this->_retvalue = $this->yystack[$this->yyidx + -2]->minor.'=>'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1254 "src/Parser/TemplateParser.y"
+ public function yy_r179(){
+ $this->_retvalue = '\''.$this->yystack[$this->yyidx + -2]->minor.'\'=>'.$this->yystack[$this->yyidx + 0]->minor;
+ }
+// line 1270 "src/Parser/TemplateParser.y"
+ public function yy_r182(){
+ $this->compiler->leaveDoubleQuote();
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor->to_smarty_php($this);
+ }
+// line 1276 "src/Parser/TemplateParser.y"
+ public function yy_r183(){
+ $this->yystack[$this->yyidx + -1]->minor->append_subtree($this, $this->yystack[$this->yyidx + 0]->minor);
+ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor;
+ }
+// line 1281 "src/Parser/TemplateParser.y"
+ public function yy_r184(){
+ $this->_retvalue = new Dq($this, $this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 1285 "src/Parser/TemplateParser.y"
+ public function yy_r185(){
+ $this->_retvalue = new Code('(string)'.$this->yystack[$this->yyidx + -1]->minor);
+ }
+// line 1289 "src/Parser/TemplateParser.y"
+ public function yy_r186(){
+ $this->_retvalue = new Code('(string)('.$this->yystack[$this->yyidx + -1]->minor.')');
+ }
+// line 1293 "src/Parser/TemplateParser.y"
+ public function yy_r187(){
+ $this->_retvalue = new Code('(string)$_smarty_tpl->getValue(\''. substr($this->yystack[$this->yyidx + 0]->minor,1) .'\')');
+ }
+// line 1305 "src/Parser/TemplateParser.y"
+ public function yy_r190(){
+ $this->_retvalue = new Tag($this, $this->yystack[$this->yyidx + 0]->minor);
+ }
+// line 1309 "src/Parser/TemplateParser.y"
+ public function yy_r191(){
+ $this->_retvalue = new DqContent($this->yystack[$this->yyidx + 0]->minor);
+ }
+
+ private $_retvalue;
+
+ public function yy_reduce($yyruleno)
+ {
+ if ($this->yyTraceFILE && $yyruleno >= 0
+ && $yyruleno < count(self::$yyRuleName)) {
+ fprintf($this->yyTraceFILE, "%sReduce (%d) [%s].\n",
+ $this->yyTracePrompt, $yyruleno,
+ self::$yyRuleName[$yyruleno]);
+ }
+
+ $this->_retvalue = $yy_lefthand_side = null;
+ if (isset(self::$yyReduceMap[$yyruleno])) {
+ // call the action
+ $this->_retvalue = null;
+ $this->{'yy_r' . self::$yyReduceMap[$yyruleno]}();
+ $yy_lefthand_side = $this->_retvalue;
+ }
+ $yygoto = self::$yyRuleInfo[$yyruleno][0];
+ $yysize = self::$yyRuleInfo[$yyruleno][1];
+ $this->yyidx -= $yysize;
+ for ($i = $yysize; $i; $i--) {
+ // pop all of the right-hand side parameters
+ array_pop($this->yystack);
+ }
+ $yyact = $this->yy_find_reduce_action($this->yystack[$this->yyidx]->stateno, $yygoto);
+ if ($yyact < self::YYNSTATE) {
+ if (!$this->yyTraceFILE && $yysize) {
+ $this->yyidx++;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = $yyact;
+ $x->major = $yygoto;
+ $x->minor = $yy_lefthand_side;
+ $this->yystack[$this->yyidx] = $x;
+ } else {
+ $this->yy_shift($yyact, $yygoto, $yy_lefthand_side);
+ }
+ } elseif ($yyact === self::YYNSTATE + self::YYNRULE + 1) {
+ $this->yy_accept();
+ }
+ }
+
+ public function yy_parse_failed()
+ {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sFail!\n", $this->yyTracePrompt);
+ } while ($this->yyidx >= 0) {
+ $this->yy_pop_parser_stack();
+ }
+ }
+
+ public function yy_syntax_error($yymajor, $TOKEN)
+ {
+// line 225 "src/Parser/TemplateParser.y"
+
+ $this->internalError = true;
+ $this->yymajor = $yymajor;
+ $this->compiler->trigger_template_error();
+ }
+
+ public function yy_accept()
+ {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sAccept!\n", $this->yyTracePrompt);
+ } while ($this->yyidx >= 0) {
+ $this->yy_pop_parser_stack();
+ }
+// line 218 "src/Parser/TemplateParser.y"
+
+ $this->successful = !$this->internalError;
+ $this->internalError = false;
+ $this->retvalue = $this->_retvalue;
+ }
+
+ public function doParse($yymajor, $yytokenvalue)
+ {
+ $yyerrorhit = 0; /* True if yymajor has invoked an error */
+
+ if ($this->yyidx === null || $this->yyidx < 0) {
+ $this->yyidx = 0;
+ $this->yyerrcnt = -1;
+ $x = (object) ['stateno' => null, 'major' => null, 'minor' => null];
+ $x->stateno = 0;
+ $x->major = 0;
+ $this->yystack = array();
+ $this->yystack[] = $x;
+ }
+ $yyendofinput = ($yymajor==0);
+
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sInput %s\n",
+ $this->yyTracePrompt, $this->yyTokenName[$yymajor]);
+ }
+
+ do {
+ $yyact = $this->yy_find_shift_action($yymajor);
+ if ($yymajor < self::YYERRORSYMBOL &&
+ !$this->yy_is_expected_token($yymajor)) {
+ // force a syntax error
+ $yyact = self::YY_ERROR_ACTION;
+ }
+ if ($yyact < self::YYNSTATE) {
+ $this->yy_shift($yyact, $yymajor, $yytokenvalue);
+ $this->yyerrcnt--;
+ if ($yyendofinput && $this->yyidx >= 0) {
+ $yymajor = 0;
+ } else {
+ $yymajor = self::YYNOCODE;
+ }
+ } elseif ($yyact < self::YYNSTATE + self::YYNRULE) {
+ $this->yy_reduce($yyact - self::YYNSTATE);
+ } elseif ($yyact === self::YY_ERROR_ACTION) {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sSyntax Error!\n",
+ $this->yyTracePrompt);
+ }
+ if (self::YYERRORSYMBOL) {
+ if ($this->yyerrcnt < 0) {
+ $this->yy_syntax_error($yymajor, $yytokenvalue);
+ }
+ $yymx = $this->yystack[$this->yyidx]->major;
+ if ($yymx === self::YYERRORSYMBOL || $yyerrorhit) {
+ if ($this->yyTraceFILE) {
+ fprintf($this->yyTraceFILE, "%sDiscard input token %s\n",
+ $this->yyTracePrompt, $this->yyTokenName[$yymajor]);
+ }
+ $this->yy_destructor($yymajor, $yytokenvalue);
+ $yymajor = self::YYNOCODE;
+ } else {
+ while ($this->yyidx >= 0 &&
+ $yymx !== self::YYERRORSYMBOL &&
+ ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE
+ ){
+ $this->yy_pop_parser_stack();
+ }
+ if ($this->yyidx < 0 || $yymajor==0) {
+ $this->yy_destructor($yymajor, $yytokenvalue);
+ $this->yy_parse_failed();
+ $yymajor = self::YYNOCODE;
+ } elseif ($yymx !== self::YYERRORSYMBOL) {
+ $u2 = 0;
+ $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2);
+ }
+ }
+ $this->yyerrcnt = 3;
+ $yyerrorhit = 1;
+ } else {
+ if ($this->yyerrcnt <= 0) {
+ $this->yy_syntax_error($yymajor, $yytokenvalue);
+ }
+ $this->yyerrcnt = 3;
+ $this->yy_destructor($yymajor, $yytokenvalue);
+ if ($yyendofinput) {
+ $this->yy_parse_failed();
+ }
+ $yymajor = self::YYNOCODE;
+ }
+ } else {
+ $this->yy_accept();
+ $yymajor = self::YYNOCODE;
+ }
+ } while ($yymajor !== self::YYNOCODE && $this->yyidx >= 0);
+ }
+}
+
diff --git a/src/includes/smarty-3.1.48/lexer/smarty_internal_templateparser.y b/src/includes/smarty-5.4.1/src/Parser/TemplateParser.y
similarity index 84%
rename from src/includes/smarty-3.1.48/lexer/smarty_internal_templateparser.y
rename to src/includes/smarty-5.4.1/src/Parser/TemplateParser.y
index 8f81202..f1e3c35 100644
--- a/src/includes/smarty-3.1.48/lexer/smarty_internal_templateparser.y
+++ b/src/includes/smarty-5.4.1/src/Parser/TemplateParser.y
@@ -9,21 +9,32 @@
%stack_size 500
%name TP_
%declare_class {
+
+namespace Smarty\Parser;
+
+use \Smarty\Lexer\TemplateLexer as Lexer;
+use \Smarty\ParseTree\Template as TemplateParseTree;
+use \Smarty\Compiler\Template as TemplateCompiler;
+use \Smarty\ParseTree\Code;
+use \Smarty\ParseTree\Dq;
+use \Smarty\ParseTree\DqContent;
+use \Smarty\ParseTree\Tag;
+
+
/**
* Smarty Template Parser Class
*
* This is the template parser.
-* It is generated from the smarty_internal_templateparser.y file
+* It is generated from the TemplateParser.y file
*
* @author Uwe Tews
*/
-class Smarty_Internal_Templateparser
+class TemplateParser
}
%include_class
{
const ERR1 = 'Security error: Call to private object member not allowed';
const ERR2 = 'Security error: Call to dynamic object member not allowed';
- const ERR3 = 'PHP in template not allowed. Use SmartyBC to enable it';
/**
* result status
@@ -61,21 +72,21 @@ class Smarty_Internal_Templateparser
/**
* root parse tree buffer
*
- * @var Smarty_Internal_ParseTree_Template
+ * @var TemplateParseTree
*/
public $root_buffer;
/**
* current parse tree object
*
- * @var Smarty_Internal_ParseTree
+ * @var \Smarty\ParseTree\Base
*/
public $current_buffer;
/**
* lexer object
*
- * @var Smarty_Internal_Templatelexer
+ * @var Lexer
*/
public $lex;
@@ -95,21 +106,21 @@ class Smarty_Internal_Templateparser
/**
* compiler object
*
- * @var Smarty_Internal_TemplateCompilerBase
+ * @var TemplateCompiler
*/
public $compiler = null;
/**
* smarty object
*
- * @var Smarty
+ * @var \Smarty\Smarty
*/
public $smarty = null;
/**
* template object
*
- * @var Smarty_Internal_Template
+ * @var \Smarty\Template
*/
public $template = null;
@@ -123,38 +134,38 @@ class Smarty_Internal_Templateparser
/**
* security object
*
- * @var Smarty_Security
+ * @var \Smarty\Security
*/
public $security = null;
/**
* template prefix array
*
- * @var \Smarty_Internal_ParseTree[]
+ * @var \Smarty\ParseTree\Base[]
*/
public $template_prefix = array();
/**
* template prefix array
*
- * @var \Smarty_Internal_ParseTree[]
+ * @var \Smarty\ParseTree\Base[]
*/
public $template_postfix = array();
/**
* constructor
*
- * @param Smarty_Internal_Templatelexer $lex
- * @param Smarty_Internal_TemplateCompilerBase $compiler
+ * @param Lexer $lex
+ * @param TemplateCompiler $compiler
*/
- public function __construct(Smarty_Internal_Templatelexer $lex, Smarty_Internal_TemplateCompilerBase $compiler)
+ public function __construct(Lexer $lex, TemplateCompiler $compiler)
{
$this->lex = $lex;
$this->compiler = $compiler;
- $this->template = $this->compiler->template;
- $this->smarty = $this->template->smarty;
- $this->security = isset($this->smarty->security_policy) ? $this->smarty->security_policy : false;
- $this->current_buffer = $this->root_buffer = new Smarty_Internal_ParseTree_Template();
+ $this->template = $this->compiler->getTemplate();
+ $this->smarty = $this->template->getSmarty();
+ $this->security = $this->smarty->security_policy ?? false;
+ $this->current_buffer = $this->root_buffer = new TemplateParseTree();
}
/**
@@ -164,7 +175,7 @@ class Smarty_Internal_Templateparser
*/
public function insertPhpCode($code)
{
- $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Tag($this, $code));
+ $this->current_buffer->append_subtree($this, new Tag($this, $code));
}
/**
@@ -186,9 +197,9 @@ class Smarty_Internal_Templateparser
*
* @param string $code
*
- * @return Smarty_Internal_ParseTree_Tag
+ * @return Tag
*/
- public function mergePrefixCode($code)
+ private function mergePrefixCode($code)
{
$tmp = '';
foreach ($this->compiler->prefix_code as $preCode) {
@@ -196,7 +207,7 @@ class Smarty_Internal_Templateparser
}
$this->compiler->prefix_code = array();
$tmp .= $code;
- return new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp, true));
+ return new Tag($this, $this->compiler->processNocacheCode($tmp));
}
}
@@ -237,16 +248,6 @@ start(res) ::= template. {
res = $this->root_buffer->to_smarty_php($this);
}
-
- // php tags
-template ::= template PHP(B). {
- $code = $this->compiler->compileTag('private_php',array(array('code' => B), array('type' => $this->lex->phpType )),array());
- if ($this->compiler->has_code && !empty($code)) {
- $tmp =''; foreach ($this->compiler->prefix_code as $code) {$tmp.=$code;} $this->compiler->prefix_code=array();
- $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp.$code,true)));
- }
-}
-
// template text
template ::= template TEXT(B). {
$text = $this->yystack[ $this->yyidx + 0 ]->minor;
@@ -255,7 +256,7 @@ template ::= template TEXT(B). {
$this->current_buffer->append_subtree($this, null);
}
- $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Text($text, $this->strip));
+ $this->current_buffer->append_subtree($this, new \Smarty\ParseTree\Text($text, $this->strip));
}
// strip on
template ::= template STRIPON. {
@@ -268,7 +269,7 @@ template ::= template STRIPOFF. {
// Literal
template ::= template LITERALSTART literal_e2(B) LITERALEND. {
- $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Text(B));
+ $this->current_buffer->append_subtree($this, new \Smarty\ParseTree\Text(B));
}
@@ -289,11 +290,9 @@ literal_e1(A) ::= . {
}
// Smarty tag
template ::= template smartytag(B). {
- if ($this->compiler->has_code) {
- $this->current_buffer->append_subtree($this, $this->mergePrefixCode(B));
- }
+ $this->current_buffer->append_subtree($this, $this->mergePrefixCode(B));
$this->compiler->has_variable_string = false;
- $this->block_nesting_level = count($this->compiler->_tag_stack);
+ $this->block_nesting_level = $this->compiler->getTagStackCount();
}
@@ -302,11 +301,12 @@ template ::= .
smartytag(A) ::= SIMPELOUTPUT(B). {
$var = trim(substr(B, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $');
+ $attributes = [];
if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) {
- A = $this->compiler->compileTag('private_print_expression',array('nocache'),array('value'=>$this->compiler->compileVariable('\''.$match[1].'\'')));
- } else {
- A = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$this->compiler->compileVariable('\''.$var.'\'')));
+ $attributes[] = 'nocache';
+ $var = $match[1];
}
+ A = $this->compiler->compilePrintExpression($this->compiler->compileVariable('\''.$var.'\''), $attributes);
}
// simple tag like {name}
@@ -320,7 +320,7 @@ smartytag(A)::= SIMPLETAG(B). {
if ($this->security) {
$this->security->isTrustedConstant($tag, $this->compiler);
}
- A = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$tag));
+ A = $this->compiler->compilePrintExpression($tag);
} else {
if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) {
A = $this->compiler->compileTag($match[1],array('\'nocache\''));
@@ -335,10 +335,10 @@ smartytag(A) ::= SMARTYBLOCKCHILDPARENT(i). {
$j = strrpos(i,'.');
if (i[$j+1] == 'c') {
// {$smarty.block.child}
- A = $this->compiler->compileTag('child',array(),array(i));
+ A = $this->compiler->compileChildBlock();
} else {
// {$smarty.block.parent}
- A = $this->compiler->compileTag('parent',array(),array(i));
+ A = $this->compiler->compileParentBlock();
}
}
@@ -351,7 +351,7 @@ smartytag(A) ::= LDEL tagbody(B) RDEL. {
}
// output with optional attributes
tagbody(A) ::= outattr(B). {
- A = $this->compiler->compileTag('private_print_expression',B[1],array('value'=>B[0]));
+ A = $this->compiler->compilePrintExpression(B[0], B[1]);
}
//
@@ -391,7 +391,7 @@ tag(res) ::= LDEL ID(i) attributes(a). {
if ($this->security) {
$this->security->isTrustedConstant(i, $this->compiler);
}
- res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i));
+ res = $this->compiler->compilePrintExpression(i, a);
} else {
res = $this->compiler->compileTag(i,a);
}
@@ -401,7 +401,7 @@ tag(res) ::= LDEL ID(i). {
if ($this->security) {
$this->security->isTrustedConstant(i, $this->compiler);
}
- res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>i));
+ res = $this->compiler->compilePrintExpression(i);
} else {
res = $this->compiler->compileTag(i,array());
}
@@ -414,7 +414,7 @@ tag(res) ::= LDEL ID(i) modifierlist(l)attributes(a). {
if ($this->security) {
$this->security->isTrustedConstant(i, $this->compiler);
}
- res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i, 'modifierlist'=>l));
+ res = $this->compiler->compilePrintExpression(i, a, l);
} else {
res = $this->compiler->compileTag(i,a, array('modifierlist'=>l));
}
@@ -430,11 +430,6 @@ tag(res) ::= LDEL ID(i) PTR ID(me) modifierlist(l) attributes(a). {
res = $this->compiler->compileTag(i,a,array('modifierlist'=>l, 'object_method'=>me));
}
- // nocache tag
-tag(res) ::= LDELMAKENOCACHE DOLLARID(i). {
- res = $this->compiler->compileTag('make_nocache',array(array('var'=>'\''.substr(i,1).'\'')));
-}
-
// {if}, {elseif} and {while} tag
tag(res) ::= LDELIF(i) expr(ie). {
$tag = trim(substr(i,$this->compiler->getLdelLength()));
@@ -620,11 +615,26 @@ expr(res) ::= value(v). {
res = v;
}
+ // nullcoalescing
+expr(res) ::= nullcoalescing(v). {
+ res = v;
+}
+
// ternary
expr(res) ::= ternary(v). {
res = v;
}
+ // ++$a / --$a
+expr(res) ::= INCDEC(i2) DOLLARID(i). {
+ res = '$_smarty_tpl->getVariable(\''. substr(i,1) .'\')->preIncDec(\'' . i2 . '\')';
+}
+
+ // $a++ / $a--
+expr(res) ::= DOLLARID(i) INCDEC(i2). {
+ res = '$_smarty_tpl->getVariable(\''. substr(i,1) .'\')->postIncDec(\'' . i2 . '\')';
+}
+
// resources/streams
expr(res) ::= DOLLARID(i) COLON ID(i2). {
res = '$_smarty_tpl->getStreamVariable(\''.substr(i,1).'://' . i2 . '\')';
@@ -653,26 +663,48 @@ expr(res) ::= expr(e1) scond(c). {
res = c . e1 . ')';
}
-expr(res) ::= expr(e1) ISIN array(a). {
- res = 'in_array('.e1.','.a.')';
+isin(res) ::= ISIN(o). {
+ static $isin = [
+ 'isin' => 'in_array(',
+ 'isnotin' => '!in_array(',
+ ];
+ $op = strtolower(str_replace(' ', '', o));
+ res = $isin[$op];
}
-expr(res) ::= expr(e1) ISIN value(v). {
- res = 'in_array('.e1.',(array)'.v.')';
+expr(res) ::= expr(e1) isin(c) array(a). {
+ res = c . e1.','.a.')';
}
+expr(res) ::= expr(e1) isin(c) value(v). {
+ res = c . e1.',(array)'.v.')';
+}
+
+// null coalescing
+nullcoalescing(res) ::= expr(v) QMARK QMARK expr(e2). {
+ res = v.' ?? '.e2;
+}
//
// ternary
//
-ternary(res) ::= OPENP expr(v) CLOSEP QMARK DOLLARID(e1) COLON expr(e2). {
+ternary(res) ::= expr(v) QMARK DOLLARID(e1) COLON expr(e2). {
res = v.' ? '. $this->compiler->compileVariable('\''.substr(e1,1).'\'') . ' : '.e2;
}
-ternary(res) ::= OPENP expr(v) CLOSEP QMARK expr(e1) COLON expr(e2). {
+ternary(res) ::= expr(v) QMARK value(e1) COLON expr(e2). {
res = v.' ? '.e1.' : '.e2;
}
+ternary(res) ::= expr(v) QMARK expr(e1) COLON expr(e2). {
+ res = v.' ? '.e1.' : '.e2;
+}
+
+// shorthand ternary
+ternary(res) ::= expr(v) QMARK COLON expr(e2). {
+ res = v.' ?: '.e2;
+}
+
// value
value(res) ::= variable(v). {
res = v;
@@ -763,7 +795,7 @@ value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
}
$prefixVar = $this->compiler->getNewPrefixVariable();
if (vi['var'] === '\'smarty\'') {
- $this->compiler->appendPrefixCode("compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>');
+ $this->compiler->appendPrefixCode("compile(array(),$this->compiler,vi['smarty_internal_index']).';?>');
} else {
$this->compiler->appendPrefixCode("compiler->compileVariable(vi['var']).vi['smarty_internal_index'].';?>');
}
@@ -773,13 +805,13 @@ value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
// Smarty tag
value(res) ::= smartytag(st). {
$prefixVar = $this->compiler->getNewPrefixVariable();
- $tmp = $this->compiler->appendCode('', st);
+ $tmp = $this->compiler->appendCode('', (string) st);
$this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, ""));
res = $prefixVar;
}
value(res) ::= value(v) modifierlist(l). {
- res = $this->compiler->compileTag('private_modifier',array(),array('value'=>v,'modifierlist'=>l));
+ res = $this->compiler->compileModifier(l, v);
}
// name space constant
value(res) ::= NAMESPACE(c). {
@@ -826,7 +858,7 @@ variable(res) ::= DOLLARID(i). {
}
variable(res) ::= varindexed(vi). {
if (vi['var'] === '\'smarty\'') {
- $smarty_var = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']);
+ $smarty_var = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']);
res = $smarty_var;
} else {
// used for array reset,next,prev,end,current
@@ -838,7 +870,7 @@ variable(res) ::= varindexed(vi). {
// variable with property
variable(res) ::= varvar(v) AT ID(p). {
- res = '$_smarty_tpl->tpl_vars['. v .']->'.p;
+ res = '$_smarty_tpl->getVariable('. v .')->'.p;
}
// object
@@ -911,11 +943,11 @@ indexdef(res) ::= DOT LDEL expr(e) RDEL. {
// section tag index
indexdef(res) ::= OPENB ID(i)CLOSEB. {
- res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\'index\']').']';
+ res = '['.(new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,'[\'section\'][\''.i.'\'][\'index\']').']';
}
indexdef(res) ::= OPENB ID(i) DOT ID(i2) CLOSEB. {
- res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\''.i2.'\']').']';
+ res = '['.(new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,'[\'section\'][\''.i.'\'][\''.i2.'\']').']';
}
indexdef(res) ::= OPENB SINGLEQUOTESTRING(s) CLOSEB. {
res = '['.s.']';
@@ -981,7 +1013,7 @@ varvarele(res) ::= LDEL expr(e) RDEL. {
//
object(res) ::= varindexed(vi) objectchain(oc). {
if (vi['var'] === '\'smarty\'') {
- res = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).oc;
+ res = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']).oc;
} else {
res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].oc;
}
@@ -1036,7 +1068,7 @@ objectelement(res)::= PTR method(f). {
// function
//
function(res) ::= ns1(f) OPENP params(p) CLOSEP. {
- res = $this->compiler->compilePHPFunctionCall(f, p);
+ res = $this->compiler->compileModifierInExpression(f, p);
}
@@ -1070,7 +1102,7 @@ params(res) ::= expr(e). {
res = array(e);
}
- // kein parameter
+ // no parameter
params(res) ::= . {
res = array();
}
@@ -1247,34 +1279,34 @@ doublequoted(res) ::= doublequoted(o1) doublequotedcontent(o2). {
}
doublequoted(res) ::= doublequotedcontent(o). {
- res = new Smarty_Internal_ParseTree_Dq($this, o);
+ res = new Dq($this, o);
}
doublequotedcontent(res) ::= BACKTICK variable(v) BACKTICK. {
- res = new Smarty_Internal_ParseTree_Code('(string)'.v);
+ res = new Code('(string)'.v);
}
doublequotedcontent(res) ::= BACKTICK expr(e) BACKTICK. {
- res = new Smarty_Internal_ParseTree_Code('(string)('.e.')');
+ res = new Code('(string)('.e.')');
}
doublequotedcontent(res) ::= DOLLARID(i). {
- res = new Smarty_Internal_ParseTree_Code('(string)$_smarty_tpl->tpl_vars[\''. substr(i,1) .'\']->value');
+ res = new Code('(string)$_smarty_tpl->getValue(\''. substr(i,1) .'\')');
}
doublequotedcontent(res) ::= LDEL variable(v) RDEL. {
- res = new Smarty_Internal_ParseTree_Code('(string)'.v);
+ res = new Code('(string)'.v);
}
doublequotedcontent(res) ::= LDEL expr(e) RDEL. {
- res = new Smarty_Internal_ParseTree_Code('(string)('.e.')');
+ res = new Code('(string)('.e.')');
}
doublequotedcontent(res) ::= smartytag(st). {
- res = new Smarty_Internal_ParseTree_Tag($this, st);
+ res = new Tag($this, st);
}
doublequotedcontent(res) ::= TEXT(o). {
- res = new Smarty_Internal_ParseTree_DqContent(o);
+ res = new DqContent(o);
}
diff --git a/src/includes/smarty-5.4.1/src/Resource/BasePlugin.php b/src/includes/smarty-5.4.1/src/Resource/BasePlugin.php
new file mode 100644
index 0000000..56f7dfa
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Resource/BasePlugin.php
@@ -0,0 +1,145 @@
+ FilePlugin::class,
+ 'string' => StringPlugin::class,
+ 'extends' => ExtendsPlugin::class,
+ 'stream' => StreamPlugin::class,
+ 'eval' => StringEval::class,
+ ];
+
+ /**
+ * Source must be recompiled on every occasion
+ *
+ * @var boolean
+ */
+ public $recompiled = false;
+
+ /**
+ * Flag if resource does allow compilation
+ *
+ * @return bool
+ */
+ public function supportsCompiledTemplates(): bool {
+ return true;
+ }
+
+ /**
+ * Check if resource must check time stamps when loading compiled or cached templates.
+ * Resources like 'extends' which use source components my disable timestamp checks on own resource.
+ * @return bool
+ */
+ public function checkTimestamps()
+ {
+ return true;
+ }
+
+ /**
+ * Load Resource Handler
+ *
+ * @param Smarty $smarty smarty object
+ * @param string $type name of the resource
+ *
+ * @return BasePlugin Resource Handler
+ * @throws Exception
+ */
+ public static function load(Smarty $smarty, $type)
+ {
+ // try smarty's cache
+ if (isset($smarty->_resource_handlers[ $type ])) {
+ return $smarty->_resource_handlers[ $type ];
+ }
+ // try registered resource
+ if (isset($smarty->registered_resources[ $type ])) {
+ return $smarty->_resource_handlers[ $type ] = $smarty->registered_resources[ $type ];
+ }
+ // try sysplugins dir
+ if (isset(self::$sysplugins[ $type ])) {
+ $_resource_class = self::$sysplugins[ $type ];
+ return $smarty->_resource_handlers[ $type ] = new $_resource_class();
+ }
+ // try plugins dir
+ $_resource_class = 'Smarty_Resource_' . \smarty_ucfirst_ascii($type);
+ if (class_exists($_resource_class, false)) {
+ return $smarty->_resource_handlers[ $type ] = new $_resource_class();
+ }
+ // try streams
+ $_known_stream = stream_get_wrappers();
+ if (in_array($type, $_known_stream)) {
+ // is known stream
+ if (is_object($smarty->security_policy)) {
+ $smarty->security_policy->isTrustedStream($type);
+ }
+ return $smarty->_resource_handlers[ $type ] = new StreamPlugin();
+ }
+ // TODO: try default_(template|config)_handler
+ // give up
+ throw new \Smarty\Exception("Unknown resource type '{$type}'");
+ }
+
+ /**
+ * Load template's source into current template object
+ *
+ * @param Source $source source object
+ *
+ * @return string template source
+ * @throws \Smarty\Exception if source cannot be loaded
+ */
+ abstract public function getContent(Source $source);
+
+ /**
+ * populate Source Object with metadata from Resource
+ *
+ * @param Source $source source object
+ * @param Template|null $_template template object
+ */
+ abstract public function populate(Source $source, \Smarty\Template $_template = null);
+
+ /**
+ * populate Source Object with timestamp and exists from Resource
+ *
+ * @param Source $source source object
+ */
+ public function populateTimestamp(Source $source)
+ {
+ // intentionally left blank
+ }
+
+ /*
+ * Check if resource must check time stamps when when loading complied or cached templates.
+ * Resources like 'extends' which use source components my disable timestamp checks on own resource.
+ *
+ * @return bool
+ */
+ /**
+ * Determine basename for compiled filename
+ *
+ * @param \Smarty\Template\Source $source source object
+ *
+ * @return string resource's basename
+ */
+ public function getBasename(\Smarty\Template\Source $source)
+ {
+ return basename(preg_replace('![^\w]+!', '_', $source->name));
+ }
+
+}
diff --git a/src/includes/smarty-5.4.1/src/Resource/CustomPlugin.php b/src/includes/smarty-5.4.1/src/Resource/CustomPlugin.php
new file mode 100644
index 0000000..b50ef7a
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Resource/CustomPlugin.php
@@ -0,0 +1,105 @@
+uid = sha1($source->type . ':' . $source->name);
+ $mtime = $this->fetchTimestamp($source->name);
+ if ($mtime !== null) {
+ $source->timestamp = $mtime;
+ } else {
+ $this->fetch($source->name, $content, $timestamp);
+ $source->timestamp = $timestamp ?? false;
+ if (isset($content)) {
+ $source->content = $content;
+ }
+ }
+ $source->exists = !!$source->timestamp;
+ }
+
+ /**
+ * Load template's source into current template object
+ *
+ * @param Source $source source object
+ *
+ * @return string template source
+ * @throws Exception if source cannot be loaded
+ */
+ public function getContent(Source $source) {
+ $this->fetch($source->name, $content, $timestamp);
+ if (isset($content)) {
+ return $content;
+ }
+ throw new Exception("Unable to read template {$source->type} '{$source->name}'");
+ }
+
+ /**
+ * Determine basename for compiled filename
+ *
+ * @param Source $source source object
+ *
+ * @return string resource's basename
+ */
+ public function getBasename(Source $source) {
+ return basename($this->generateSafeName($source->name));
+ }
+
+ /**
+ * Removes special characters from $name and limits its length to 127 characters.
+ *
+ * @param $name
+ *
+ * @return string
+ */
+ private function generateSafeName($name): string {
+ return substr(preg_replace('/[^A-Za-z0-9._]/', '', (string)$name), 0, 127);
+ }
+}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_resource_extends.php b/src/includes/smarty-5.4.1/src/Resource/ExtendsPlugin.php
similarity index 50%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_resource_extends.php
rename to src/includes/smarty-5.4.1/src/Resource/ExtendsPlugin.php
index 8094693..0f9c9de 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_resource_extends.php
+++ b/src/includes/smarty-5.4.1/src/Resource/ExtendsPlugin.php
@@ -1,59 +1,45 @@
name);
- $smarty = &$source->smarty;
+ $smarty = $source->getSmarty();
$exists = true;
foreach ($components as $component) {
- /* @var \Smarty_Template_Source $_s */
- $_s = Smarty_Template_Source::load(null, $smarty, $component);
- if ($_s->type === 'php') {
- throw new SmartyException("Resource type {$_s->type} cannot be used with the extends resource type");
- }
+ $_s = Source::load(null, $smarty, $component);
$sources[ $_s->uid ] = $_s;
- $uid .= $_s->filepath;
+ $uid .= $_s->uid;
if ($_template) {
$exists = $exists && $_s->exists;
}
}
$source->components = $sources;
- $source->filepath = $_s->filepath;
- $source->uid = sha1($uid . $source->smarty->_joined_template_dir);
+ $source->uid = sha1($uid . $source->getSmarty()->_joined_template_dir);
$source->exists = $exists;
if ($_template) {
$source->timestamp = $_s->timestamp;
@@ -63,12 +49,12 @@ class Smarty_Internal_Resource_Extends extends Smarty_Resource
/**
* populate Source Object with timestamp and exists from Resource
*
- * @param Smarty_Template_Source $source source object
+ * @param Source $source source object
*/
- public function populateTimestamp(Smarty_Template_Source $source)
+ public function populateTimestamp(Source $source)
{
$source->exists = true;
- /* @var \Smarty_Template_Source $_s */
+ /* @var Source $_s */
foreach ($source->components as $_s) {
$source->exists = $source->exists && $_s->exists;
}
@@ -78,19 +64,19 @@ class Smarty_Internal_Resource_Extends extends Smarty_Resource
/**
* Load template's source from files into current template object
*
- * @param Smarty_Template_Source $source source object
+ * @param Source $source source object
*
* @return string template source
- * @throws SmartyException if source cannot be loaded
+ * @throws \Smarty\Exception if source cannot be loaded
*/
- public function getContent(Smarty_Template_Source $source)
+ public function getContent(Source $source)
{
if (!$source->exists) {
- throw new SmartyException("Unable to load template '{$source->type}:{$source->name}'");
+ throw new \Smarty\Exception("Unable to load '{$source->type}:{$source->name}'");
}
$_components = array_reverse($source->components);
$_content = '';
- /* @var \Smarty_Template_Source $_s */
+ /* @var Source $_s */
foreach ($_components as $_s) {
// read content
$_content .= $_s->getContent();
@@ -101,13 +87,17 @@ class Smarty_Internal_Resource_Extends extends Smarty_Resource
/**
* Determine basename for compiled filename
*
- * @param Smarty_Template_Source $source source object
+ * @param Source $source source object
*
* @return string resource's basename
*/
- public function getBasename(Smarty_Template_Source $source)
+ public function getBasename(Source $source)
{
- return str_replace(':', '.', basename($source->filepath));
+ $search = array(':');
+ if (\Smarty\Smarty::$_IS_WINDOWS) {
+ $search = array(':', '|');
+ }
+ return str_replace($search, '.', basename($source->getResourceName()));
}
/*
diff --git a/src/includes/smarty-5.4.1/src/Resource/FilePlugin.php b/src/includes/smarty-5.4.1/src/Resource/FilePlugin.php
new file mode 100644
index 0000000..c595957
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Resource/FilePlugin.php
@@ -0,0 +1,183 @@
+uid = sha1(
+ $source->name . ($source->isConfig ? $source->getSmarty()->_joined_config_dir :
+ $source->getSmarty()->_joined_template_dir)
+ );
+
+ if ($path = $this->getFilePath($source->name, $source->getSmarty(), $source->isConfig)) {
+ if (isset($source->getSmarty()->security_policy) && is_object($source->getSmarty()->security_policy)) {
+ $source->getSmarty()->security_policy->isTrustedResourceDir($path, $source->isConfig);
+ }
+ $source->exists = true;
+ $source->timestamp = filemtime($path);
+ } else {
+ $source->timestamp = $source->exists = false;
+ }
+ }
+
+ /**
+ * populate Source Object with timestamp and exists from Resource
+ *
+ * @param Source $source source object
+ */
+ public function populateTimestamp(Source $source) {
+ $path = $this->getFilePath($source->name, $source->getSmarty(), $source->isConfig);
+ if (!$source->exists) {
+ $source->exists = ($path !== false && is_file($path));
+ }
+ if ($source->exists && $path !== false) {
+ $source->timestamp = filemtime($path);
+ } else {
+ $source->timestamp = 0;
+ }
+ }
+
+ /**
+ * Load template's source from file into current template object
+ *
+ * @param Source $source source object
+ *
+ * @return string template source
+ * @throws Exception if source cannot be loaded
+ */
+ public function getContent(Source $source) {
+ if ($source->exists) {
+ return file_get_contents($this->getFilePath($source->getResourceName(), $source->getSmarty(), $source->isConfig()));
+ }
+ throw new Exception(
+ 'Unable to read ' . ($source->isConfig ? 'config' : 'template') .
+ " {$source->type} '{$source->name}'"
+ );
+ }
+
+ /**
+ * Determine basename for compiled filename
+ *
+ * @param Source $source source object
+ *
+ * @return string resource's basename
+ */
+ public function getBasename(Source $source) {
+ return basename($source->getResourceName());
+ }
+
+ /**
+ * build template filepath by traversing the template_dir array
+ *
+ * @param $file
+ * @param Smarty $smarty
+ * @param bool $isConfig
+ *
+ * @return string fully qualified filepath
+ */
+ public function getFilePath($file, \Smarty\Smarty $smarty, bool $isConfig = false) {
+ // absolute file ?
+ if ($file[0] === '/' || $file[1] === ':') {
+ $file = $smarty->_realpath($file, true);
+ return is_file($file) ? $file : false;
+ }
+
+ // normalize DIRECTORY_SEPARATOR
+ if (strpos($file, DIRECTORY_SEPARATOR === '/' ? '\\' : '/') !== false) {
+ $file = str_replace(DIRECTORY_SEPARATOR === '/' ? '\\' : '/', DIRECTORY_SEPARATOR, $file);
+ }
+ $_directories = $smarty->getTemplateDir(null, $isConfig);
+ // template_dir index?
+ if ($file[0] === '[' && preg_match('#^\[([^\]]+)\](.+)$#', $file, $fileMatch)) {
+ $file = $fileMatch[2];
+ $_indices = explode(',', $fileMatch[1]);
+ $_index_dirs = [];
+ foreach ($_indices as $index) {
+ $index = trim($index);
+ // try string indexes
+ if (isset($_directories[$index])) {
+ $_index_dirs[] = $_directories[$index];
+ } elseif (is_numeric($index)) {
+ // try numeric index
+ $index = (int)$index;
+ if (isset($_directories[$index])) {
+ $_index_dirs[] = $_directories[$index];
+ } else {
+ // try at location index
+ $keys = array_keys($_directories);
+ if (isset($_directories[$keys[$index]])) {
+ $_index_dirs[] = $_directories[$keys[$index]];
+ }
+ }
+ }
+ }
+ if (empty($_index_dirs)) {
+ // index not found
+ return false;
+ } else {
+ $_directories = $_index_dirs;
+ }
+ }
+ // relative file name?
+ foreach ($_directories as $_directory) {
+ $path = $_directory . $file;
+ if (is_file($path)) {
+ return (strpos($path, '.' . DIRECTORY_SEPARATOR) !== false) ? $smarty->_realpath($path) : $path;
+ }
+ }
+ if (!isset($_index_dirs)) {
+ // Could be relative to cwd
+ $path = $smarty->_realpath($file, true);
+ if (is_file($path)) {
+ return $path;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the timestamp of the resource indicated by $resourceName, or false if it doesn't exist.
+ *
+ * @param string $resourceName
+ * @param Smarty $smarty
+ * @param bool $isConfig
+ *
+ * @return false|int
+ */
+ public function getResourceNameTimestamp(string $resourceName, \Smarty\Smarty $smarty, bool $isConfig = false) {
+ if ($path = $this->getFilePath($resourceName, $smarty, $isConfig)) {
+ return filemtime($path);
+ }
+ return false;
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Resource/RecompiledPlugin.php b/src/includes/smarty-5.4.1/src/Resource/RecompiledPlugin.php
new file mode 100644
index 0000000..f1c64bc
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Resource/RecompiledPlugin.php
@@ -0,0 +1,50 @@
+uid = false;
+ $source->content = $this->getContent($source);
+ $source->timestamp = $source->exists = !!$source->content;
+ }
+
+ /**
+ * Load template's source from stream into current template object
+ *
+ * @param Source $source source object
+ *
+ * @return string template source
+ */
+ public function getContent(Source $source) {
+
+ if (strpos($source->getResourceName(), '://') !== false) {
+ $filepath = $source->getResourceName();
+ } else {
+ $filepath = str_replace(':', '://', $source->getFullResourceName());
+ }
+
+ $t = '';
+ // the availability of the stream has already been checked in Smarty\Resource\Base::fetch()
+ $fp = fopen($filepath, 'r+');
+ if ($fp) {
+ while (!feof($fp) && ($current_line = fgets($fp)) !== false) {
+ $t .= $current_line;
+ }
+ fclose($fp);
+ return $t;
+ } else {
+ return false;
+ }
+ }
+
+}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_resource_eval.php b/src/includes/smarty-5.4.1/src/Resource/StringEval.php
similarity index 53%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_resource_eval.php
rename to src/includes/smarty-5.4.1/src/Resource/StringEval.php
index 3b552a5..5c35e74 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_resource_eval.php
+++ b/src/includes/smarty-5.4.1/src/Resource/StringEval.php
@@ -1,9 +1,14 @@
uid = $source->filepath = sha1($source->name);
+ $source->uid = sha1($source->name);
$source->timestamp = $source->exists = true;
}
/**
* Load template's source from $resource_name into current template object
*
- * @uses decode() to decode base64 and urlencoded template_resources
- *
- * @param Smarty_Template_Source $source source object
+ * @param \Smarty\Template\Source $source source object
*
* @return string template source
+ *@uses decode() to decode base64 and urlencoded template_resources
+ *
*/
- public function getContent(Smarty_Template_Source $source)
+ public function getContent(\Smarty\Template\Source $source)
{
return $this->decode($source->name);
}
@@ -66,28 +71,14 @@ class Smarty_Internal_Resource_Eval extends Smarty_Resource_Recompiled
return $string;
}
- /**
- * modify resource_name according to resource handlers specifications
- *
- * @param Smarty $smarty Smarty instance
- * @param string $resource_name resource_name to make unique
- * @param boolean $isConfig flag for config resource
- *
- * @return string unique resource name
- */
- public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false)
- {
- return get_class($this) . '#' . $this->decode($resource_name);
- }
-
/**
* Determine basename for compiled filename
*
- * @param Smarty_Template_Source $source source object
+ * @param \Smarty\Template\Source $source source object
*
* @return string resource's basename
*/
- public function getBasename(Smarty_Template_Source $source)
+ public function getBasename(\Smarty\Template\Source $source)
{
return '';
}
diff --git a/src/includes/smarty-5.4.1/src/Resource/StringPlugin.php b/src/includes/smarty-5.4.1/src/Resource/StringPlugin.php
new file mode 100644
index 0000000..6b5bee4
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Resource/StringPlugin.php
@@ -0,0 +1,94 @@
+uid = sha1($source->name);
+ $source->timestamp = $source->exists = true;
+ }
+
+ /**
+ * Load template's source from $resource_name into current template object
+ *
+ * @param Source $source source object
+ *
+ * @return string template source
+ * @uses decode() to decode base64 and urlencoded template_resources
+ *
+ */
+ public function getContent(Source $source) {
+ return $this->decode($source->name);
+ }
+
+ /**
+ * decode base64 and urlencode
+ *
+ * @param string $string template_resource to decode
+ *
+ * @return string decoded template_resource
+ */
+ protected function decode($string) {
+ // decode if specified
+ if (($pos = strpos($string, ':')) !== false) {
+ if (!strncmp($string, 'base64', 6)) {
+ return base64_decode(substr($string, 7));
+ } elseif (!strncmp($string, 'urlencode', 9)) {
+ return urldecode(substr($string, 10));
+ }
+ }
+ return $string;
+ }
+
+ /**
+ * Determine basename for compiled filename
+ * Always returns an empty string.
+ *
+ * @param Source $source source object
+ *
+ * @return string resource's basename
+ */
+ public function getBasename(Source $source) {
+ return '';
+ }
+
+ /*
+ * Disable timestamp checks for string resource.
+ *
+ * @return bool
+ */
+ /**
+ * @return bool
+ */
+ public function checkTimestamps() {
+ return false;
+ }
+}
diff --git a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_block.php b/src/includes/smarty-5.4.1/src/Runtime/Block.php
similarity index 81%
rename from src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_block.php
rename to src/includes/smarty-5.4.1/src/Runtime/Block.php
index 9956d64..90eab9c 100644
--- a/src/includes/smarty-3.1.48/libs/sysplugins/smarty_internal_block.php
+++ b/src/includes/smarty-5.4.1/src/Runtime/Block.php
@@ -1,13 +1,15 @@
registerCallbacks($_template);
+
+ $this->captureStack[] = [
+ $buffer,
+ $assign,
+ $append,
+ ];
+ $this->captureCount++;
+ ob_start();
+ }
+
+ /**
+ * Register callbacks in template class
+ *
+ * @param \Smarty\Template $_template
+ */
+ private function registerCallbacks(Template $_template) {
+
+ foreach ($_template->startRenderCallbacks as $callback) {
+ if (is_array($callback) && get_class($callback[0]) == self::class) {
+ // already registered
+ return;
+ }
+ }
+
+ $_template->startRenderCallbacks[] = [
+ $this,
+ 'startRender',
+ ];
+ $_template->endRenderCallbacks[] = [
+ $this,
+ 'endRender',
+ ];
+ $this->startRender($_template);
+ }
+
+ /**
+ * Start render callback
+ *
+ * @param \Smarty\Template $_template
+ */
+ public function startRender(Template $_template) {
+ $this->countStack[] = $this->captureCount;
+ $this->captureCount = 0;
+ }
+
+ /**
+ * Close capture section
+ *
+ * @param \Smarty\Template $_template
+ *
+ * @throws \Smarty\Exception
+ */
+ public function close(Template $_template) {
+ if ($this->captureCount) {
+ [$buffer, $assign, $append] = array_pop($this->captureStack);
+ $this->captureCount--;
+ if (isset($assign)) {
+ $_template->assign($assign, ob_get_contents());
+ }
+ if (isset($append)) {
+ $_template->append($append, ob_get_contents());
+ }
+ $this->namedBuffer[$buffer] = ob_get_clean();
+ } else {
+ $this->error($_template);
+ }
+ }
+
+ /**
+ * Error exception on not matching {capture}{/capture}
+ *
+ * @param \Smarty\Template $_template
+ *
+ * @throws \Smarty\Exception
+ */
+ public function error(Template $_template) {
+ throw new \Smarty\Exception("Not matching {capture}{/capture} in '{$_template->template_resource}'");
+ }
+
+ /**
+ * Return content of named capture buffer by key or as array
+ *
+ * @param \Smarty\Template $_template
+ * @param string|null $name
+ *
+ * @return string|string[]|null
+ */
+ public function getBuffer(Template $_template, $name = null) {
+ if (isset($name)) {
+ return $this->namedBuffer[$name] ?? null;
+ } else {
+ return $this->namedBuffer;
+ }
+ }
+
+ /**
+ * End render callback
+ *
+ * @param \Smarty\Template $_template
+ *
+ * @throws \Smarty\Exception
+ */
+ public function endRender(Template $_template) {
+ if ($this->captureCount) {
+ $this->error($_template);
+ } else {
+ $this->captureCount = array_pop($this->countStack);
+ }
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Runtime/DefaultPluginHandlerRuntime.php b/src/includes/smarty-5.4.1/src/Runtime/DefaultPluginHandlerRuntime.php
new file mode 100644
index 0000000..ad6ed74
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Runtime/DefaultPluginHandlerRuntime.php
@@ -0,0 +1,73 @@
+defaultPluginHandler = $defaultPluginHandler;
+ }
+
+ public function hasPlugin($tag, $plugin_type): bool {
+ if ($this->defaultPluginHandler === null) {
+ return false;
+ }
+
+ $callback = null;
+
+ // these are not used here
+ $script = null;
+ $cacheable = null;
+
+ return (call_user_func_array(
+ $this->defaultPluginHandler,
+ [
+ $tag,
+ $plugin_type,
+ null, // This used to pass $this->template, but this parameter has been removed in 5.0
+ &$callback,
+ &$script,
+ &$cacheable,
+ ]
+ ) && $callback);
+ }
+
+ /**
+ * @throws Exception
+ */
+ public function getCallback($tag, $plugin_type) {
+
+ if ($this->defaultPluginHandler === null) {
+ return false;
+ }
+
+ $callback = null;
+
+ // these are not used here
+ $script = null;
+ $cacheable = null;
+
+ if (call_user_func_array(
+ $this->defaultPluginHandler,
+ [
+ $tag,
+ $plugin_type,
+ null, // This used to pass $this->template, but this parameter has been removed in 5.0
+ &$callback,
+ &$script,
+ &$cacheable,
+ ]
+ ) && $callback) {
+ return $callback;
+ }
+ throw new Exception("Default plugin handler: Returned callback for '{$tag}' not callable at runtime");
+ }
+
+}
\ No newline at end of file
diff --git a/src/includes/smarty-5.4.1/src/Runtime/ForeachRuntime.php b/src/includes/smarty-5.4.1/src/Runtime/ForeachRuntime.php
new file mode 100644
index 0000000..06da7d5
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Runtime/ForeachRuntime.php
@@ -0,0 +1,160 @@
+count($from);
+ }
+ } else {
+ settype($from, 'array');
+ }
+ }
+ if (!isset($total)) {
+ $total = empty($from) ? 0 : ($needTotal ? count($from) : 1);
+ }
+ if ($tpl->hasVariable($item)) {
+ $saveVars['item'] = [
+ $item,
+ $tpl->getVariable($item)->getValue(),
+ ];
+ }
+ $tpl->assign($item,null);
+ if ($total === 0) {
+ $from = null;
+ } else {
+ if ($key) {
+ if ($tpl->hasVariable($key)) {
+ $saveVars['key'] = [
+ $key,
+ clone $tpl->getVariable($key),
+ ];
+ }
+ $tpl->assign($key, null);
+ }
+ }
+ if ($needTotal) {
+ $tpl->getVariable($item)->total = $total;
+ }
+ if ($name) {
+ $namedVar = "__smarty_foreach_{$name}";
+ if ($tpl->hasVariable($namedVar)) {
+ $saveVars['named'] = [
+ $namedVar,
+ clone $tpl->getVariable($namedVar),
+ ];
+ }
+ $namedProp = [];
+ if (isset($properties['total'])) {
+ $namedProp['total'] = $total;
+ }
+ if (isset($properties['iteration'])) {
+ $namedProp['iteration'] = 0;
+ }
+ if (isset($properties['index'])) {
+ $namedProp['index'] = -1;
+ }
+ if (isset($properties['show'])) {
+ $namedProp['show'] = ($total > 0);
+ }
+ $tpl->assign($namedVar, $namedProp);
+ }
+ $this->stack[] = $saveVars;
+ return $from;
+ }
+
+ /**
+ * [util function] counts an array, arrayAccess/traversable or PDOStatement object
+ *
+ * @param mixed $value
+ *
+ * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0
+ * for empty elements
+ * @throws \Exception
+ */
+ public function count($value): int
+ {
+ if ($value instanceof \IteratorAggregate) {
+ // Note: getIterator() returns a Traversable, not an Iterator
+ // thus rewind() and valid() methods may not be present
+ return iterator_count($value->getIterator());
+ } elseif ($value instanceof \Iterator) {
+ return $value instanceof \Generator ? 1 : iterator_count($value);
+ } elseif ($value instanceof \Countable) {
+ return count($value);
+ }
+ return count((array) $value);
+ }
+
+ /**
+ * Restore saved variables
+ *
+ * will be called by {break n} or {continue n} for the required number of levels
+ *
+ * @param \Smarty\Template $tpl
+ * @param int $levels number of levels
+ */
+ public function restore(Template $tpl, $levels = 1) {
+ while ($levels) {
+ $saveVars = array_pop($this->stack);
+ if (!empty($saveVars)) {
+ if (isset($saveVars['item'])) {
+ $tpl->getVariable($saveVars['item'][0])->setValue($saveVars['item'][1]);
+ }
+ if (isset($saveVars['key'])) {
+ $tpl->setVariable($saveVars['key'][0], $saveVars['key'][1]);
+ }
+ if (isset($saveVars['named'])) {
+ $tpl->setVariable($saveVars['named'][0], $saveVars['named'][1]);
+ }
+ }
+ $levels--;
+ }
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Runtime/InheritanceRuntime.php b/src/includes/smarty-5.4.1/src/Runtime/InheritanceRuntime.php
new file mode 100644
index 0000000..ffd7aae
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Runtime/InheritanceRuntime.php
@@ -0,0 +1,243 @@
+state === 3 && (strpos($tpl->template_resource, 'extendsall') === false)) {
+ $tpl->setInheritance(clone $tpl->getSmarty()->getRuntime('Inheritance'));
+ $tpl->getInheritance()->init($tpl, $initChild, $blockNames);
+ return;
+ }
+ ++$this->tplIndex;
+ $this->sources[$this->tplIndex] = $tpl->getSource();
+ // start of child sub template(s)
+ if ($initChild) {
+ $this->state = 1;
+ if (!$this->inheritanceLevel) {
+ //grab any output of child templates
+ ob_start();
+ }
+ ++$this->inheritanceLevel;
+ }
+ // if state was waiting for parent change state to parent
+ if ($this->state === 2) {
+ $this->state = 3;
+ }
+ }
+
+ /**
+ * End of child template(s)
+ * - if outer level is reached flush output buffer and switch to wait for parent template state
+ *
+ * @param \Smarty\Template $tpl
+ * @param null|string $template optional name of inheritance parent template
+ *
+ * @throws \Exception
+ * @throws \Smarty\Exception
+ */
+ public function endChild(Template $tpl, $template = null, ?string $currentDir = null) {
+ --$this->inheritanceLevel;
+ if (!$this->inheritanceLevel) {
+ ob_end_clean();
+ $this->state = 2;
+ }
+ if (isset($template)) {
+ $tpl->renderSubTemplate(
+ $template,
+ $tpl->cache_id,
+ $tpl->compile_id,
+ $tpl->caching ? \Smarty\Template::CACHING_NOCACHE_CODE : 0,
+ $tpl->cache_lifetime,
+ [],
+ null,
+ $currentDir
+ );
+ }
+ }
+
+ /**
+ * \Smarty\Runtime\Block constructor.
+ * - if outer level {block} of child template ($state === 1) save it as child root block
+ * - otherwise process inheritance and render
+ *
+ * @param \Smarty\Template $tpl
+ * @param $className
+ * @param string $name
+ * @param int|null $tplIndex index of outer level {block} if nested
+ *
+ * @throws \Smarty\Exception
+ */
+ public function instanceBlock(Template $tpl, $className, $name, $tplIndex = null) {
+ $block = new $className($name, isset($tplIndex) ? $tplIndex : $this->tplIndex);
+ if (isset($this->childRoot[$name])) {
+ $block->child = $this->childRoot[$name];
+ }
+ if ($this->state === 1) {
+ $this->childRoot[$name] = $block;
+ return;
+ }
+ // make sure we got child block of child template of current block
+ while ($block->child && $block->child->child && $block->tplIndex <= $block->child->tplIndex) {
+ $block->child = $block->child->child;
+ }
+ $this->processBlock($tpl, $block);
+ }
+
+ /**
+ * Goto child block or render this
+ *
+ * @param Template $tpl
+ * @param \Smarty\Runtime\Block $block
+ * @param \Smarty\Runtime\Block|null $parent
+ *
+ * @throws Exception
+ */
+ private function processBlock(
+ Template $tpl,
+ \Smarty\Runtime\Block $block,
+ \Smarty\Runtime\Block $parent = null
+ ) {
+ if ($block->hide && !isset($block->child)) {
+ return;
+ }
+ if (isset($block->child) && $block->child->hide && !isset($block->child->child)) {
+ $block->child = null;
+ }
+ $block->parent = $parent;
+ if ($block->append && !$block->prepend && isset($parent)) {
+ $this->callParent($tpl, $block, '\'{block append}\'');
+ }
+ if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) {
+ $this->callBlock($block, $tpl);
+ } else {
+ $this->processBlock($tpl, $block->child, $block);
+ }
+ if ($block->prepend && isset($parent)) {
+ $this->callParent($tpl, $block, '{block prepend}');
+ if ($block->append) {
+ if ($block->callsChild || !isset($block->child)
+ || ($block->child->hide && !isset($block->child->child))
+ ) {
+ $this->callBlock($block, $tpl);
+ } else {
+ $this->processBlock($tpl, $block->child, $block);
+ }
+ }
+ }
+ $block->parent = null;
+ }
+
+ /**
+ * Render child on \$smarty.block.child
+ *
+ * @param Template $tpl
+ * @param \Smarty\Runtime\Block $block
+ *
+ * @return null|string block content
+ * @throws Exception
+ */
+ public function callChild(Template $tpl, \Smarty\Runtime\Block $block) {
+ if (isset($block->child)) {
+ $this->processBlock($tpl, $block->child, $block);
+ }
+ }
+
+ /**
+ * Render parent block on \$smarty.block.parent or {block append/prepend}
+ *
+ * @param Template $tpl
+ * @param \Smarty\Runtime\Block $block
+ * @param string $tag
+ *
+ * @return null|string block content
+ * @throws Exception
+ */
+ public function callParent(Template $tpl, \Smarty\Runtime\Block $block) {
+ if (isset($block->parent)) {
+ $this->callBlock($block->parent, $tpl);
+ } else {
+ throw new Exception("inheritance: illegal '{\$smarty.block.parent}' used in child template '" .
+ "{$tpl->getInheritance()->sources[$block->tplIndex]->getResourceName()}' block '{$block->name}'");
+ }
+ }
+
+ /**
+ * render block
+ *
+ * @param \Smarty\Runtime\Block $block
+ * @param Template $tpl
+ */
+ public function callBlock(\Smarty\Runtime\Block $block, Template $tpl) {
+ $this->sourceStack[] = $tpl->getSource();
+ $tpl->setSource($this->sources[$block->tplIndex]);
+ $block->callBlock($tpl);
+ $tpl->setSource(array_pop($this->sourceStack));
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Runtime/TplFunctionRuntime.php b/src/includes/smarty-5.4.1/src/Runtime/TplFunctionRuntime.php
new file mode 100644
index 0000000..6c4b93d
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Runtime/TplFunctionRuntime.php
@@ -0,0 +1,144 @@
+tplFunctions[$name] ?? ($tpl->getSmarty()->tplFunctions[$name] ?? null);
+ if (!isset($funcParam)) {
+ throw new \Smarty\Exception("Unable to find template function '{$name}'");
+ }
+
+ if (!$tpl->caching || ($tpl->caching && $nocache)) {
+ $function = $funcParam['call_name'];
+ } else {
+ if (isset($funcParam['call_name_caching'])) {
+ $function = $funcParam['call_name_caching'];
+ } else {
+ $function = $funcParam['call_name'];
+ }
+ }
+ if (!function_exists($function) && !$this->addTplFuncToCache($tpl, $name, $function)) {
+ throw new \Smarty\Exception("Unable to find template function '{$name}'");
+ }
+
+ $tpl->pushStack();
+ $function($tpl, $params);
+ $tpl->popStack();
+ }
+
+ /**
+ * Register template functions defined by template
+ *
+ * @param \Smarty|\Smarty\Template|\Smarty\TemplateBase $obj
+ * @param array $tplFunctions source information array of
+ * template functions defined
+ * in template
+ * @param bool $override if true replace existing
+ * functions with same name
+ */
+ public function registerTplFunctions(TemplateBase $obj, $tplFunctions, $override = true) {
+ $obj->tplFunctions =
+ $override ? array_merge($obj->tplFunctions, $tplFunctions) : array_merge($tplFunctions, $obj->tplFunctions);
+ // make sure that the template functions are known in parent templates
+ if ($obj->_isSubTpl()) {
+ $this->registerTplFunctions($obj->parent, $tplFunctions, false);
+ } else {
+ $obj->getSmarty()->tplFunctions = $override ? array_merge($obj->getSmarty()->tplFunctions, $tplFunctions) :
+ array_merge($tplFunctions, $obj->getSmarty()->tplFunctions);
+ }
+ }
+
+ /**
+ * Return source parameter array for single or all template functions
+ *
+ * @param \Smarty\Template $tpl template object
+ * @param null|string $name template function name
+ *
+ * @return array|bool|mixed
+ */
+ public function getTplFunction(Template $tpl, $name = null) {
+ if (isset($name)) {
+ return $tpl->tplFunctions[$name] ?? ($tpl->getSmarty()->tplFunctions[$name] ?? false);
+ } else {
+ return empty($tpl->tplFunctions) ? $tpl->getSmarty()->tplFunctions : $tpl->tplFunctions;
+ }
+ }
+
+ /**
+ * Add template function to cache file for nocache calls
+ *
+ * @param Template $tpl
+ * @param string $_name template function name
+ * @param string $_function PHP function name
+ *
+ * @return bool
+ * @throws Exception
+ */
+ private function addTplFuncToCache(Template $tpl, $_name, $_function) {
+ $funcParam = $tpl->tplFunctions[$_name];
+ if (is_file($funcParam['compiled_filepath'])) {
+ // read compiled file
+ $code = file_get_contents($funcParam['compiled_filepath']);
+ // grab template function
+ if (preg_match("/\/\* {$_function} \*\/([\S\s]*?)\/\*\/ {$_function} \*\//", $code, $match)) {
+ // grab source info from file dependency
+ preg_match("/\s*'{$funcParam['uid']}'([\S\s]*?)\),/", $code, $match1);
+ unset($code);
+ // make PHP function known
+ eval($match[0]);
+ if (function_exists($_function)) {
+
+ // Some magic code existed here, testing if the cached property had been set
+ // and then bubbling up until it found a parent template that had the cached property.
+ // This is no longer possible, so somehow this might break.
+
+ // add template function code to cache file
+ $content = $tpl->getCached()->readCache($tpl);
+ if ($content) {
+ // check if we must update file dependency
+ if (!preg_match("/'{$funcParam['uid']}'(.*?)'nocache_hash'/", $content, $match2)) {
+ $content = preg_replace("/('file_dependency'(.*?)\()/", "\\1{$match1[0]}", $content);
+ }
+ $tpl->getCached()->writeCache(
+ $tpl,
+ preg_replace('/\s*\?>\s*$/', "\n", $content) .
+ "\n" . preg_replace(
+ [
+ '/^\s*<\?php\s+/',
+ '/\s*\?>\s*$/',
+ ],
+ "\n",
+ $match[0]
+ )
+ );
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/src/includes/smarty-5.4.1/src/Security.php b/src/includes/smarty-5.4.1/src/Security.php
new file mode 100644
index 0000000..250b3bc
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Security.php
@@ -0,0 +1,560 @@
+ array('method_1', 'method_2'), // allowed methods listed
+ * 'class_2' => array(), // all methods of class allowed
+ * )
+ * If set to null none is allowed.
+ *
+ * @var array
+ */
+ public $trusted_static_methods = [];
+
+ /**
+ * This is an array of trusted static properties.
+ * If empty access to all static classes and properties is allowed.
+ * Format:
+ * array (
+ * 'class_1' => array('prop_1', 'prop_2'), // allowed properties listed
+ * 'class_2' => array(), // all properties of class allowed
+ * )
+ * If set to null none is allowed.
+ *
+ * @var array
+ */
+ public $trusted_static_properties = [];
+
+ /**
+ * This is an array of allowed tags.
+ * If empty no restriction by allowed_tags.
+ *
+ * @var array
+ */
+ public $allowed_tags = [];
+
+ /**
+ * This is an array of disabled tags.
+ * If empty no restriction by disabled_tags.
+ *
+ * @var array
+ */
+ public $disabled_tags = [];
+
+ /**
+ * This is an array of allowed modifier plugins.
+ * If empty no restriction by allowed_modifiers.
+ *
+ * @var array
+ */
+ public $allowed_modifiers = [];
+
+ /**
+ * This is an array of disabled modifier plugins.
+ * If empty no restriction by disabled_modifiers.
+ *
+ * @var array
+ */
+ public $disabled_modifiers = [];
+
+ /**
+ * This is an array of disabled special $smarty variables.
+ *
+ * @var array
+ */
+ public $disabled_special_smarty_vars = [];
+
+ /**
+ * This is an array of trusted streams.
+ * If empty all streams are allowed.
+ * To disable all streams set $streams = null.
+ *
+ * @var array
+ */
+ public $streams = ['file'];
+
+ /**
+ * + flag if constants can be accessed from template
+ *
+ * @var boolean
+ */
+ public $allow_constants = true;
+
+ /**
+ * + flag if super globals can be accessed from template
+ *
+ * @var boolean
+ */
+ public $allow_super_globals = true;
+
+ /**
+ * max template nesting level
+ *
+ * @var int
+ */
+ public $max_template_nesting = 0;
+
+ /**
+ * current template nesting level
+ *
+ * @var int
+ */
+ private $_current_template_nesting = 0;
+
+ /**
+ * Cache for $resource_dir lookup
+ *
+ * @var array
+ */
+ protected $_resource_dir = [];
+
+ /**
+ * Cache for $template_dir lookup
+ *
+ * @var array
+ */
+ protected $_template_dir = [];
+
+ /**
+ * Cache for $config_dir lookup
+ *
+ * @var array
+ */
+ protected $_config_dir = [];
+
+ /**
+ * Cache for $secure_dir lookup
+ *
+ * @var array
+ */
+ protected $_secure_dir = [];
+
+ /**
+ * @param Smarty $smarty
+ */
+ public function __construct(Smarty $smarty) {
+ $this->smarty = $smarty;
+ }
+
+ /**
+ * Check if static class is trusted.
+ *
+ * @param string $class_name
+ * @param object $compiler compiler object
+ *
+ * @return boolean true if class is trusted
+ */
+ public function isTrustedStaticClass($class_name, $compiler) {
+ if (isset($this->static_classes)
+ && (empty($this->static_classes) || in_array($class_name, $this->static_classes))
+ ) {
+ return true;
+ }
+ $compiler->trigger_template_error("access to static class '{$class_name}' not allowed by security setting");
+ return false; // should not, but who knows what happens to the compiler in the future?
+ }
+
+ /**
+ * Check if static class method/property is trusted.
+ *
+ * @param string $class_name
+ * @param string $params
+ * @param object $compiler compiler object
+ *
+ * @return boolean true if class method is trusted
+ */
+ public function isTrustedStaticClassAccess($class_name, $params, $compiler) {
+ if (!isset($params[2])) {
+ // fall back
+ return $this->isTrustedStaticClass($class_name, $compiler);
+ }
+ if ($params[2] === 'method') {
+ $allowed = $this->trusted_static_methods;
+ $name = substr($params[0], 0, strpos($params[0], '('));
+ } else {
+ $allowed = $this->trusted_static_properties;
+ // strip '$'
+ $name = substr($params[0], 1);
+ }
+ if (isset($allowed)) {
+ if (empty($allowed)) {
+ // fall back
+ return $this->isTrustedStaticClass($class_name, $compiler);
+ }
+ if (isset($allowed[$class_name])
+ && (empty($allowed[$class_name]) || in_array($name, $allowed[$class_name]))
+ ) {
+ return true;
+ }
+ }
+ $compiler->trigger_template_error("access to static class '{$class_name}' {$params[2]} '{$name}' not allowed by security setting");
+ return false; // should not, but who knows what happens to the compiler in the future?
+ }
+
+ /**
+ * Check if tag is trusted.
+ *
+ * @param string $tag_name
+ * @param object $compiler compiler object
+ *
+ * @return boolean true if tag is trusted
+ */
+ public function isTrustedTag($tag_name, $compiler) {
+ $tag_name = strtolower($tag_name);
+
+ // check for internal always required tags
+ if (in_array($tag_name, ['assign', 'call'])) {
+ return true;
+ }
+ // check security settings
+ if (empty($this->allowed_tags)) {
+ if (empty($this->disabled_tags) || !in_array($tag_name, $this->disabled_tags)) {
+ return true;
+ } else {
+ $compiler->trigger_template_error("tag '{$tag_name}' disabled by security setting", null, true);
+ }
+ } elseif (in_array($tag_name, $this->allowed_tags) && !in_array($tag_name, $this->disabled_tags)) {
+ return true;
+ } else {
+ $compiler->trigger_template_error("tag '{$tag_name}' not allowed by security setting", null, true);
+ }
+ return false; // should not, but who knows what happens to the compiler in the future?
+ }
+
+ /**
+ * Check if special $smarty variable is trusted.
+ *
+ * @param string $var_name
+ * @param object $compiler compiler object
+ *
+ * @return boolean true if tag is trusted
+ */
+ public function isTrustedSpecialSmartyVar($var_name, $compiler) {
+ if (!in_array($var_name, $this->disabled_special_smarty_vars)) {
+ return true;
+ } else {
+ $compiler->trigger_template_error(
+ "special variable '\$smarty.{$var_name}' not allowed by security setting",
+ null,
+ true
+ );
+ }
+ return false; // should not, but who knows what happens to the compiler in the future?
+ }
+
+ /**
+ * Check if modifier plugin is trusted.
+ *
+ * @param string $modifier_name
+ * @param object $compiler compiler object
+ *
+ * @return boolean true if tag is trusted
+ */
+ public function isTrustedModifier($modifier_name, $compiler) {
+ // check for internal always allowed modifier
+ if (in_array($modifier_name, ['default'])) {
+ return true;
+ }
+ // check security settings
+ if (empty($this->allowed_modifiers)) {
+ if (empty($this->disabled_modifiers) || !in_array($modifier_name, $this->disabled_modifiers)) {
+ return true;
+ } else {
+ $compiler->trigger_template_error(
+ "modifier '{$modifier_name}' disabled by security setting",
+ null,
+ true
+ );
+ }
+ } elseif (in_array($modifier_name, $this->allowed_modifiers)
+ && !in_array($modifier_name, $this->disabled_modifiers)
+ ) {
+ return true;
+ } else {
+ $compiler->trigger_template_error(
+ "modifier '{$modifier_name}' not allowed by security setting",
+ null,
+ true
+ );
+ }
+ return false; // should not, but who knows what happens to the compiler in the future?
+ }
+
+ /**
+ * Check if constants are enabled or trusted
+ *
+ * @param string $const constant name
+ * @param object $compiler compiler object
+ *
+ * @return bool
+ */
+ public function isTrustedConstant($const, $compiler) {
+ if (in_array($const, ['true', 'false', 'null'])) {
+ return true;
+ }
+ if (!empty($this->trusted_constants)) {
+ if (!in_array(strtolower($const), $this->trusted_constants)) {
+ $compiler->trigger_template_error("Security: access to constant '{$const}' not permitted");
+ return false;
+ }
+ return true;
+ }
+ if ($this->allow_constants) {
+ return true;
+ }
+ $compiler->trigger_template_error("Security: access to constants not permitted");
+ return false;
+ }
+
+ /**
+ * Check if stream is trusted.
+ *
+ * @param string $stream_name
+ *
+ * @return boolean true if stream is trusted
+ * @throws Exception if stream is not trusted
+ */
+ public function isTrustedStream($stream_name) {
+ if (isset($this->streams) && (empty($this->streams) || in_array($stream_name, $this->streams))) {
+ return true;
+ }
+ throw new Exception("stream '{$stream_name}' not allowed by security setting");
+ }
+
+ /**
+ * Check if directory of file resource is trusted.
+ *
+ * @param string $filepath
+ * @param null|bool $isConfig
+ *
+ * @return bool true if directory is trusted
+ * @throws \Smarty\Exception if directory is not trusted
+ */
+ public function isTrustedResourceDir($filepath, $isConfig = null) {
+ $_dir = $this->smarty->getTemplateDir();
+ if ($this->_template_dir !== $_dir) {
+ $this->_updateResourceDir($this->_template_dir, $_dir);
+ $this->_template_dir = $_dir;
+ }
+ $_dir = $this->smarty->getConfigDir();
+ if ($this->_config_dir !== $_dir) {
+ $this->_updateResourceDir($this->_config_dir, $_dir);
+ $this->_config_dir = $_dir;
+ }
+ if ($this->_secure_dir !== $this->secure_dir) {
+ $this->secure_dir = (array)$this->secure_dir;
+ foreach ($this->secure_dir as $k => $d) {
+ $this->secure_dir[$k] = $this->smarty->_realpath($d . DIRECTORY_SEPARATOR, true);
+ }
+ $this->_updateResourceDir($this->_secure_dir, $this->secure_dir);
+ $this->_secure_dir = $this->secure_dir;
+ }
+ $addPath = $this->_checkDir($filepath, $this->_resource_dir);
+ if ($addPath !== false) {
+ $this->_resource_dir = array_merge($this->_resource_dir, $addPath);
+ }
+ return true;
+ }
+
+ /**
+ * Check if URI (e.g. {fetch} or {html_image}) is trusted
+ * To simplify things, isTrustedUri() resolves all input to "{$PROTOCOL}://{$HOSTNAME}".
+ * So "http://username:password@hello.world.example.org:8080/some-path?some=query-string"
+ * is reduced to "http://hello.world.example.org" prior to applying the patters from {@link $trusted_uri}.
+ *
+ * @param string $uri
+ *
+ * @return boolean true if URI is trusted
+ * @throws Exception if URI is not trusted
+ * @uses $trusted_uri for list of patterns to match against $uri
+ */
+ public function isTrustedUri($uri) {
+ $_uri = parse_url($uri);
+ if (!empty($_uri['scheme']) && !empty($_uri['host'])) {
+ $_uri = $_uri['scheme'] . '://' . $_uri['host'];
+ foreach ($this->trusted_uri as $pattern) {
+ if (preg_match($pattern, $_uri)) {
+ return true;
+ }
+ }
+ }
+ throw new Exception("URI '{$uri}' not allowed by security setting");
+ }
+
+ /**
+ * Remove old directories and its sub folders, add new directories
+ *
+ * @param array $oldDir
+ * @param array $newDir
+ */
+ private function _updateResourceDir($oldDir, $newDir) {
+ foreach ($oldDir as $directory) {
+ // $directory = $this->smarty->_realpath($directory, true);
+ $length = strlen($directory);
+ foreach ($this->_resource_dir as $dir) {
+ if (substr($dir, 0, $length) === $directory) {
+ unset($this->_resource_dir[$dir]);
+ }
+ }
+ }
+ foreach ($newDir as $directory) {
+ // $directory = $this->smarty->_realpath($directory, true);
+ $this->_resource_dir[$directory] = true;
+ }
+ }
+
+ /**
+ * Check if file is inside a valid directory
+ *
+ * @param string $filepath
+ * @param array $dirs valid directories
+ *
+ * @return array|bool
+ * @throws \Smarty\Exception
+ */
+ private function _checkDir($filepath, $dirs) {
+ $directory = dirname($this->smarty->_realpath($filepath, true)) . DIRECTORY_SEPARATOR;
+ $_directory = [];
+ if (!preg_match('#[\\\\/][.][.][\\\\/]#', $directory)) {
+ while (true) {
+ // test if the directory is trusted
+ if (isset($dirs[$directory])) {
+ return $_directory;
+ }
+ // abort if we've reached root
+ if (!preg_match('#[\\\\/][^\\\\/]+[\\\\/]$#', $directory)) {
+ // give up
+ break;
+ }
+ // remember the directory to add it to _resource_dir in case we're successful
+ $_directory[$directory] = true;
+ // bubble up one level
+ $directory = preg_replace('#[\\\\/][^\\\\/]+[\\\\/]$#', DIRECTORY_SEPARATOR, $directory);
+ }
+ }
+ // give up
+ throw new Exception(sprintf('Smarty Security: not trusted file path \'%s\' ', $filepath));
+ }
+
+ /**
+ * Loads security class and enables security
+ *
+ * @param \Smarty $smarty
+ * @param string|Security $security_class if a string is used, it must be class-name
+ *
+ * @return \Smarty current Smarty instance for chaining
+ * @throws \Smarty\Exception when an invalid class name is provided
+ */
+ public static function enableSecurity(Smarty $smarty, $security_class) {
+ if ($security_class instanceof Security) {
+ $smarty->security_policy = $security_class;
+ return $smarty;
+ } elseif (is_object($security_class)) {
+ throw new Exception("Class '" . get_class($security_class) . "' must extend \\Smarty\\Security.");
+ }
+ if ($security_class === null) {
+ $security_class = $smarty->security_class;
+ }
+ if (!class_exists($security_class)) {
+ throw new Exception("Security class '$security_class' is not defined");
+ } elseif ($security_class !== Security::class && !is_subclass_of($security_class, Security::class)) {
+ throw new Exception("Class '$security_class' must extend " . Security::class . ".");
+ } else {
+ $smarty->security_policy = new $security_class($smarty);
+ }
+ return $smarty;
+ }
+
+ /**
+ * Start template processing
+ *
+ * @param $template
+ *
+ * @throws Exception
+ */
+ public function startTemplate($template) {
+ if ($this->max_template_nesting > 0 && $this->_current_template_nesting++ >= $this->max_template_nesting) {
+ throw new Exception("maximum template nesting level of '{$this->max_template_nesting}' exceeded when calling '{$template->template_resource}'");
+ }
+ }
+
+ /**
+ * Exit template processing
+ */
+ public function endTemplate() {
+ if ($this->max_template_nesting > 0) {
+ $this->_current_template_nesting--;
+ }
+ }
+
+ /**
+ * Register callback functions call at start/end of template rendering
+ *
+ * @param \Smarty\Template $template
+ */
+ public function registerCallBacks(Template $template) {
+ $template->startRenderCallbacks[] = [$this, 'startTemplate'];
+ $template->endRenderCallbacks[] = [$this, 'endTemplate'];
+ }
+}
diff --git a/src/includes/smarty-5.4.1/src/Smarty.php b/src/includes/smarty-5.4.1/src/Smarty.php
new file mode 100644
index 0000000..a896179
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Smarty.php
@@ -0,0 +1,2239 @@
+
+ * @author Uwe Tews
+ * @author Rodney Rehm
+ * @author Simon Wisselink
+ */
+
+/**
+ * This is the main Smarty class
+ */
+class Smarty extends \Smarty\TemplateBase {
+
+ /**
+ * smarty version
+ */
+ const SMARTY_VERSION = '5.4.1';
+
+ /**
+ * define caching modes
+ */
+ const CACHING_OFF = 0;
+ const CACHING_LIFETIME_CURRENT = 1;
+ const CACHING_LIFETIME_SAVED = 2;
+ /**
+ * define constant for clearing cache files be saved expiration dates
+ */
+ const CLEAR_EXPIRED = -1;
+ /**
+ * define compile check modes
+ */
+ const COMPILECHECK_OFF = 0;
+ const COMPILECHECK_ON = 1;
+ /**
+ * filter types
+ */
+ const FILTER_POST = 'post';
+ const FILTER_PRE = 'pre';
+ const FILTER_OUTPUT = 'output';
+ const FILTER_VARIABLE = 'variable';
+ /**
+ * plugin types
+ */
+ const PLUGIN_FUNCTION = 'function';
+ const PLUGIN_BLOCK = 'block';
+ const PLUGIN_COMPILER = 'compiler';
+ const PLUGIN_MODIFIER = 'modifier';
+ const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
+
+ /**
+ * The character set to adhere to (defaults to "UTF-8")
+ */
+ public static $_CHARSET = 'UTF-8';
+
+ /**
+ * The date format to be used internally
+ * (accepts date() and strftime())
+ */
+ public static $_DATE_FORMAT = '%b %e, %Y';
+
+ /**
+ * Flag denoting if PCRE should run in UTF-8 mode
+ */
+ public static $_UTF8_MODIFIER = 'u';
+
+ /**
+ * Flag denoting if operating system is windows
+ */
+ public static $_IS_WINDOWS = false;
+
+ /**
+ * auto literal on delimiters with whitespace
+ *
+ * @var boolean
+ */
+ public $auto_literal = true;
+
+ /**
+ * display error on not assigned variables
+ *
+ * @var boolean
+ */
+ public $error_unassigned = false;
+
+ /**
+ * flag if template_dir is normalized
+ *
+ * @var bool
+ */
+ public $_templateDirNormalized = false;
+
+ /**
+ * joined template directory string used in cache keys
+ *
+ * @var string
+ */
+ public $_joined_template_dir = null;
+
+ /**
+ * flag if config_dir is normalized
+ *
+ * @var bool
+ */
+ public $_configDirNormalized = false;
+
+ /**
+ * joined config directory string used in cache keys
+ *
+ * @var string
+ */
+ public $_joined_config_dir = null;
+
+ /**
+ * default template handler
+ *
+ * @var callable
+ */
+ public $default_template_handler_func = null;
+
+ /**
+ * default config handler
+ *
+ * @var callable
+ */
+ public $default_config_handler_func = null;
+
+ /**
+ * default plugin handler
+ *
+ * @var callable
+ */
+ private $default_plugin_handler_func = null;
+
+ /**
+ * flag if template_dir is normalized
+ *
+ * @var bool
+ */
+ public $_compileDirNormalized = false;
+
+ /**
+ * flag if template_dir is normalized
+ *
+ * @var bool
+ */
+ public $_cacheDirNormalized = false;
+
+ /**
+ * force template compiling?
+ *
+ * @var boolean
+ */
+ public $force_compile = false;
+
+ /**
+ * use sub dirs for compiled/cached files?
+ *
+ * @var boolean
+ */
+ public $use_sub_dirs = false;
+
+ /**
+ * merge compiled includes
+ *
+ * @var boolean
+ */
+ public $merge_compiled_includes = false;
+
+ /**
+ * force cache file creation
+ *
+ * @var boolean
+ */
+ public $force_cache = false;
+
+ /**
+ * template left-delimiter
+ *
+ * @var string
+ */
+ private $left_delimiter = "{";
+
+ /**
+ * template right-delimiter
+ *
+ * @var string
+ */
+ private $right_delimiter = "}";
+
+ /**
+ * array of strings which shall be treated as literal by compiler
+ *
+ * @var array string
+ */
+ public $literals = [];
+
+ /**
+ * class name
+ * This should be instance of \Smarty\Security.
+ *
+ * @var string
+ * @see \Smarty\Security
+ */
+ public $security_class = \Smarty\Security::class;
+
+ /**
+ * implementation of security class
+ *
+ * @var \Smarty\Security
+ */
+ public $security_policy = null;
+
+ /**
+ * debug mode
+ * Setting this to true enables the debug-console. Setting it to 2 enables individual Debug Console window by
+ * template name.
+ *
+ * @var boolean|int
+ */
+ public $debugging = false;
+
+ /**
+ * This determines if debugging is enable-able from the browser.
+ *
+ * NONE => no debugging control allowed
+ * URL => enable debugging when SMARTY_DEBUG is found in the URL.
+ *
+ *
+ * @var string
+ */
+ public $debugging_ctrl = 'NONE';
+
+ /**
+ * Name of debugging URL-param.
+ * Only used when $debugging_ctrl is set to 'URL'.
+ * The name of the URL-parameter that activates debugging.
+ *
+ * @var string
+ */
+ public $smarty_debug_id = 'SMARTY_DEBUG';
+
+ /**
+ * Path of debug template.
+ *
+ * @var string
+ */
+ public $debug_tpl = null;
+
+ /**
+ * When set, smarty uses this value as error_reporting-level.
+ *
+ * @var int
+ */
+ public $error_reporting = null;
+
+ /**
+ * Controls whether variables with the same name overwrite each other.
+ *
+ * @var boolean
+ */
+ public $config_overwrite = true;
+
+ /**
+ * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
+ *
+ * @var boolean
+ */
+ public $config_booleanize = true;
+
+ /**
+ * Controls whether hidden config sections/vars are read from the file.
+ *
+ * @var boolean
+ */
+ public $config_read_hidden = false;
+
+ /**
+ * locking concurrent compiles
+ *
+ * @var boolean
+ */
+ public $compile_locking = true;
+
+ /**
+ * Controls whether cache resources should use locking mechanism
+ *
+ * @var boolean
+ */
+ public $cache_locking = false;
+
+ /**
+ * seconds to wait for acquiring a lock before ignoring the write lock
+ *
+ * @var float
+ */
+ public $locking_timeout = 10;
+
+ /**
+ * resource type used if none given
+ * Must be a valid key of $registered_resources.
+ *
+ * @var string
+ */
+ public $default_resource_type = 'file';
+
+ /**
+ * cache resource
+ * Must be a subclass of \Smarty\Cacheresource\Base
+ *
+ * @var \Smarty\Cacheresource\Base
+ */
+ private $cacheResource;
+
+ /**
+ * config type
+ *
+ * @var string
+ */
+ public $default_config_type = 'file';
+
+ /**
+ * check If-Modified-Since headers
+ *
+ * @var boolean
+ */
+ public $cache_modified_check = false;
+
+ /**
+ * registered plugins
+ *
+ * @var array
+ */
+ public $registered_plugins = [];
+
+ /**
+ * registered objects
+ *
+ * @var array
+ */
+ public $registered_objects = [];
+
+ /**
+ * registered classes
+ *
+ * @var array
+ */
+ public $registered_classes = [];
+
+ /**
+ * registered resources
+ *
+ * @var array
+ */
+ public $registered_resources = [];
+
+ /**
+ * registered cache resources
+ *
+ * @var array
+ * @deprecated since 5.0
+ */
+ private $registered_cache_resources = [];
+
+ /**
+ * default modifier
+ *
+ * @var array
+ */
+ public $default_modifiers = [];
+
+ /**
+ * autoescape variable output
+ *
+ * @var boolean
+ */
+ public $escape_html = false;
+
+ /**
+ * start time for execution time calculation
+ *
+ * @var int
+ */
+ public $start_time = 0;
+
+ /**
+ * internal flag to enable parser debugging
+ *
+ * @var bool
+ */
+ public $_parserdebug = false;
+
+ /**
+ * Debug object
+ *
+ * @var \Smarty\Debug
+ */
+ public $_debug = null;
+
+ /**
+ * template directory
+ *
+ * @var array
+ */
+ protected $template_dir = ['./templates/'];
+
+ /**
+ * flags for normalized template directory entries
+ *
+ * @var array
+ */
+ protected $_processedTemplateDir = [];
+
+ /**
+ * config directory
+ *
+ * @var array
+ */
+ protected $config_dir = ['./configs/'];
+
+ /**
+ * flags for normalized template directory entries
+ *
+ * @var array
+ */
+ protected $_processedConfigDir = [];
+
+ /**
+ * compile directory
+ *
+ * @var string
+ */
+ protected $compile_dir = './templates_c/';
+
+ /**
+ * cache directory
+ *
+ * @var string
+ */
+ protected $cache_dir = './cache/';
+
+ /**
+ * PHP7 Compatibility mode
+ *
+ * @var bool
+ */
+ private $isMutingUndefinedOrNullWarnings = false;
+
+ /**
+ * Cache of loaded resource handlers.
+ *
+ * @var array
+ */
+ public $_resource_handlers = [];
+
+ /**
+ * Cache of loaded cacheresource handlers.
+ *
+ * @var array
+ */
+ public $_cacheresource_handlers = [];
+
+ /**
+ * List of extensions
+ *
+ * @var ExtensionInterface[]
+ */
+ private $extensions = [];
+ /**
+ * @var BCPluginsAdapter
+ */
+ private $BCPluginsAdapter;
+
+ /**
+ * Initialize new Smarty object
+ */
+ public function __construct() {
+
+ $this->start_time = microtime(true);
+ // Check if we're running on Windows
+ \Smarty\Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
+ // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
+ if (\Smarty\Smarty::$_CHARSET !== 'UTF-8') {
+ \Smarty\Smarty::$_UTF8_MODIFIER = '';
+ }
+
+ $this->BCPluginsAdapter = new BCPluginsAdapter($this);
+
+ $this->extensions[] = new CoreExtension();
+ $this->extensions[] = new DefaultExtension();
+ $this->extensions[] = $this->BCPluginsAdapter;
+
+ $this->cacheResource = new File();
+ }
+
+ /**
+ * Load an additional extension.
+ *
+ * @return void
+ */
+ public function addExtension(ExtensionInterface $extension) {
+ $this->extensions[] = $extension;
+ }
+
+ /**
+ * Returns all loaded extensions
+ *
+ * @return array|ExtensionInterface[]
+ */
+ public function getExtensions(): array {
+ return $this->extensions;
+ }
+
+ /**
+ * Replace the entire list extensions, allowing you to determine the exact order of the extensions.
+ *
+ * @param ExtensionInterface[] $extensions
+ *
+ * @return void
+ */
+ public function setExtensions(array $extensions): void {
+ $this->extensions = $extensions;
+ }
+
+ /**
+ * Check if a template resource exists
+ *
+ * @param string $resource_name template name
+ *
+ * @return bool status
+ * @throws \Smarty\Exception
+ */
+ public function templateExists($resource_name) {
+ // create source object
+ $source = Template\Source::load(null, $this, $resource_name);
+ return $source->exists;
+ }
+
+ /**
+ * Loads security class and enables security
+ *
+ * @param string|\Smarty\Security $security_class if a string is used, it must be class-name
+ *
+ * @return static current Smarty instance for chaining
+ * @throws \Smarty\Exception
+ */
+ public function enableSecurity($security_class = null) {
+ \Smarty\Security::enableSecurity($this, $security_class);
+ return $this;
+ }
+
+ /**
+ * Disable security
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function disableSecurity() {
+ $this->security_policy = null;
+ return $this;
+ }
+
+ /**
+ * Add template directory(s)
+ *
+ * @param string|array $template_dir directory(s) of template sources
+ * @param string $key of the array element to assign the template dir to
+ * @param bool $isConfig true for config_dir
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function addTemplateDir($template_dir, $key = null, $isConfig = false) {
+ if ($isConfig) {
+ $processed = &$this->_processedConfigDir;
+ $dir = &$this->config_dir;
+ $this->_configDirNormalized = false;
+ } else {
+ $processed = &$this->_processedTemplateDir;
+ $dir = &$this->template_dir;
+ $this->_templateDirNormalized = false;
+ }
+ if (is_array($template_dir)) {
+ foreach ($template_dir as $k => $v) {
+ if (is_int($k)) {
+ // indexes are not merged but appended
+ $dir[] = $v;
+ } else {
+ // string indexes are overridden
+ $dir[$k] = $v;
+ unset($processed[$key]);
+ }
+ }
+ } else {
+ if ($key !== null) {
+ // override directory at specified index
+ $dir[$key] = $template_dir;
+ unset($processed[$key]);
+ } else {
+ // append new directory
+ $dir[] = $template_dir;
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Get template directories
+ *
+ * @param mixed $index index of directory to get, null to get all
+ * @param bool $isConfig true for config_dir
+ *
+ * @return array|string list of template directories, or directory of $index
+ */
+ public function getTemplateDir($index = null, $isConfig = false) {
+ if ($isConfig) {
+ $dir = &$this->config_dir;
+ } else {
+ $dir = &$this->template_dir;
+ }
+ if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) {
+ $this->_normalizeTemplateConfig($isConfig);
+ }
+ if ($index !== null) {
+ return isset($dir[$index]) ? $dir[$index] : null;
+ }
+ return $dir;
+ }
+
+ /**
+ * Set template directory
+ *
+ * @param string|array $template_dir directory(s) of template sources
+ * @param bool $isConfig true for config_dir
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function setTemplateDir($template_dir, $isConfig = false) {
+ if ($isConfig) {
+ $this->config_dir = [];
+ $this->_processedConfigDir = [];
+ } else {
+ $this->template_dir = [];
+ $this->_processedTemplateDir = [];
+ }
+ $this->addTemplateDir($template_dir, null, $isConfig);
+ return $this;
+ }
+
+ /**
+ * Adds a template directory before any existing directoires
+ *
+ * @param string $new_template_dir directory of template sources
+ * @param bool $is_config true for config_dir
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function prependTemplateDir($new_template_dir, $is_config = false) {
+ $current_template_dirs = $is_config ? $this->config_dir : $this->template_dir;
+ array_unshift($current_template_dirs, $new_template_dir);
+ $this->setTemplateDir($current_template_dirs, $is_config);
+ return $this;
+ }
+
+ /**
+ * Add config directory(s)
+ *
+ * @param string|array $config_dir directory(s) of config sources
+ * @param mixed $key key of the array element to assign the config dir to
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function addConfigDir($config_dir, $key = null) {
+ return $this->addTemplateDir($config_dir, $key, true);
+ }
+
+ /**
+ * Get config directory
+ *
+ * @param mixed $index index of directory to get, null to get all
+ *
+ * @return array configuration directory
+ */
+ public function getConfigDir($index = null) {
+ return $this->getTemplateDir($index, true);
+ }
+
+ /**
+ * Set config directory
+ *
+ * @param $config_dir
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function setConfigDir($config_dir) {
+ return $this->setTemplateDir($config_dir, true);
+ }
+
+ /**
+ * Registers plugin to be used in templates
+ *
+ * @param string $type plugin type
+ * @param string $name name of template tag
+ * @param callable $callback PHP callback to register
+ * @param bool $cacheable if true (default) this function is cache able
+ *
+ * @return $this
+ * @throws \Smarty\Exception
+ *
+ * @api Smarty::registerPlugin()
+ */
+ public function registerPlugin($type, $name, $callback, $cacheable = true) {
+ if (isset($this->registered_plugins[$type][$name])) {
+ throw new Exception("Plugin tag '{$name}' already registered");
+ } elseif (!is_callable($callback) && !class_exists($callback)) {
+ throw new Exception("Plugin '{$name}' not callable");
+ } else {
+ $this->registered_plugins[$type][$name] = [$callback, (bool)$cacheable];
+ }
+ return $this;
+ }
+
+ /**
+ * Returns plugin previously registered using ::registerPlugin as a numerical array as follows or null if not found:
+ * [
+ * 0 => the callback
+ * 1 => (bool) $cacheable
+ * 2 => (array) $cache_attr
+ * ]
+ *
+ * @param string $type plugin type
+ * @param string $name name of template tag
+ *
+ * @return array|null
+ *
+ * @api Smarty::unregisterPlugin()
+ */
+ public function getRegisteredPlugin($type, $name): ?array {
+ if (isset($this->registered_plugins[$type][$name])) {
+ return $this->registered_plugins[$type][$name];
+ }
+ return null;
+ }
+
+ /**
+ * Unregisters plugin previously registered using ::registerPlugin
+ *
+ * @param string $type plugin type
+ * @param string $name name of template tag
+ *
+ * @return $this
+ *
+ * @api Smarty::unregisterPlugin()
+ */
+ public function unregisterPlugin($type, $name) {
+ if (isset($this->registered_plugins[$type][$name])) {
+ unset($this->registered_plugins[$type][$name]);
+ }
+ return $this;
+ }
+
+ /**
+ * Adds directory of plugin files
+ *
+ * @param null|array|string $plugins_dir
+ *
+ * @return static current Smarty instance for chaining
+ * @deprecated since 5.0
+ */
+ public function addPluginsDir($plugins_dir) {
+ trigger_error('Using Smarty::addPluginsDir() to load plugins is deprecated and will be ' .
+ 'removed in a future release. Use Smarty::addExtension() to add an extension or Smarty::registerPlugin to ' .
+ 'quickly register a plugin using a callback function.', E_USER_DEPRECATED);
+
+ foreach ((array)$plugins_dir as $v) {
+ $path = $this->_realpath(rtrim($v ?? '', '/\\') . DIRECTORY_SEPARATOR, true);
+ $this->BCPluginsAdapter->loadPluginsFromDir($path);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get plugin directories
+ *
+ * @return array list of plugin directories
+ * @deprecated since 5.0
+ */
+ public function getPluginsDir() {
+ trigger_error('Using Smarty::getPluginsDir() is deprecated and will be ' .
+ 'removed in a future release. It will always return an empty array.', E_USER_DEPRECATED);
+ return [];
+ }
+
+ /**
+ * Set plugins directory
+ *
+ * @param string|array $plugins_dir directory(s) of plugins
+ *
+ * @return static current Smarty instance for chaining
+ * @deprecated since 5.0
+ */
+ public function setPluginsDir($plugins_dir) {
+ trigger_error('Using Smarty::getPluginsDir() is deprecated and will be ' .
+ 'removed in a future release. For now, it will remove the DefaultExtension from the extensions list and ' .
+ 'proceed to call Smartyy::addPluginsDir..', E_USER_DEPRECATED);
+
+ $this->extensions = array_filter(
+ $this->extensions,
+ function ($extension) {
+ return !($extension instanceof DefaultExtension);
+ }
+ );
+
+ return $this->addPluginsDir($plugins_dir);
+ }
+
+ /**
+ * Registers a default plugin handler
+ *
+ * @param callable $callback class/method name
+ *
+ * @return $this
+ * @throws Exception if $callback is not callable
+ *
+ * @api Smarty::registerDefaultPluginHandler()
+ *
+ * @deprecated since 5.0
+ */
+ public function registerDefaultPluginHandler($callback) {
+
+ trigger_error('Using Smarty::registerDefaultPluginHandler() is deprecated and will be ' .
+ 'removed in a future release. Please rewrite your plugin handler as an extension.',
+ E_USER_DEPRECATED);
+
+ if (is_callable($callback)) {
+ $this->default_plugin_handler_func = $callback;
+ } else {
+ throw new Exception("Default plugin handler '$callback' not callable");
+ }
+ return $this;
+ }
+
+ /**
+ * Get compiled directory
+ *
+ * @return string path to compiled templates
+ */
+ public function getCompileDir() {
+ if (!$this->_compileDirNormalized) {
+ $this->_normalizeDir('compile_dir', $this->compile_dir);
+ $this->_compileDirNormalized = true;
+ }
+ return $this->compile_dir;
+ }
+
+ /**
+ *
+ * @param string $compile_dir directory to store compiled templates in
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function setCompileDir($compile_dir) {
+ $this->_normalizeDir('compile_dir', $compile_dir);
+ $this->_compileDirNormalized = true;
+ return $this;
+ }
+
+ /**
+ * Get cache directory
+ *
+ * @return string path of cache directory
+ */
+ public function getCacheDir() {
+ if (!$this->_cacheDirNormalized) {
+ $this->_normalizeDir('cache_dir', $this->cache_dir);
+ $this->_cacheDirNormalized = true;
+ }
+ return $this->cache_dir;
+ }
+
+ /**
+ * Set cache directory
+ *
+ * @param string $cache_dir directory to store cached templates in
+ *
+ * @return static current Smarty instance for chaining
+ */
+ public function setCacheDir($cache_dir) {
+ $this->_normalizeDir('cache_dir', $cache_dir);
+ $this->_cacheDirNormalized = true;
+ return $this;
+ }
+
+ private $templates = [];
+
+ /**
+ * Creates a template object
+ *
+ * @param string $template_name
+ * @param mixed $cache_id cache id to be used with this template
+ * @param mixed $compile_id compile id to be used with this template
+ * @param null $parent next higher level of Smarty variables
+ *
+ * @return Template template object
+ * @throws Exception
+ */
+ public function createTemplate($template_name, $cache_id = null, $compile_id = null, $parent = null): Template {
+
+ $data = [];
+
+ // Shuffle params for backward compatibility: if 2nd param is an object, it's the parent
+ if (is_object($cache_id)) {
+ $parent = $cache_id;
+ $cache_id = null;
+ }
+
+ // Shuffle params for backward compatibility: if 2nd param is an array, it's data
+ if (is_array($cache_id)) {
+ $data = $cache_id;
+ $cache_id = null;
+ }
+
+ return $this->doCreateTemplate($template_name, $cache_id, $compile_id, $parent, null, null, false, $data);
+ }
+
+ /**
+ * Get unique template id
+ *
+ * @param string $resource_name
+ * @param null|mixed $cache_id
+ * @param null|mixed $compile_id
+ * @param null $caching
+ *
+ * @return string
+ */
+ private function generateUniqueTemplateId(
+ $resource_name,
+ $cache_id = null,
+ $compile_id = null,
+ $caching = null
+ ): string {
+ // defaults for optional params
+ $cache_id = $cache_id ?? $this->cache_id;
+ $compile_id = $compile_id ?? $this->compile_id;
+ $caching = (int)$caching ?? $this->caching;
+
+ // Add default resource type to resource name if it is missing
+ if (strpos($resource_name, ':') === false) {
+ $resource_name = "{$this->default_resource_type}:{$resource_name}";
+ }
+
+ $_templateId = $resource_name . '#' . $cache_id . '#' . $compile_id . '#' . $caching;
+
+ // hash very long IDs to prevent problems with filename length
+ // do not hash shorter IDs, so they remain recognizable
+ if (strlen($_templateId) > 150) {
+ $_templateId = sha1($_templateId);
+ }
+
+ return $_templateId;
+ }
+
+ /**
+ * Normalize path
+ * - remove /./ and /../
+ * - make it absolute if required
+ *
+ * @param string $path file path
+ * @param bool $realpath if true - convert to absolute
+ * false - convert to relative
+ * null - keep as it is but
+ * remove /./ /../
+ *
+ * @return string
+ */
+ public function _realpath($path, $realpath = null) {
+ $nds = ['/' => '\\', '\\' => '/'];
+ preg_match(
+ '%^(?(?:[[:alpha:]]:[\\\\/]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?(.*))$%u',
+ $path,
+ $parts
+ );
+ $path = $parts['path'];
+ if ($parts['root'] === '\\') {
+ $parts['root'] = substr(getcwd(), 0, 2) . $parts['root'];
+ } else {
+ if ($realpath !== null && !$parts['root']) {
+ $path = getcwd() . DIRECTORY_SEPARATOR . $path;
+ }
+ }
+ // normalize DIRECTORY_SEPARATOR
+ $path = str_replace($nds[DIRECTORY_SEPARATOR], DIRECTORY_SEPARATOR, $path);
+ $parts['root'] = str_replace($nds[DIRECTORY_SEPARATOR], DIRECTORY_SEPARATOR, $parts['root']);
+ do {
+ $path = preg_replace(
+ ['#[\\\\/]{2}#', '#[\\\\/][.][\\\\/]#', '#[\\\\/]([^\\\\/.]+)[\\\\/][.][.][\\\\/]#'],
+ DIRECTORY_SEPARATOR,
+ $path,
+ -1,
+ $count
+ );
+ } while ($count > 0);
+ return $realpath !== false ? $parts['root'] . $path : str_ireplace(getcwd(), '.', $parts['root'] . $path);
+ }
+
+ /**
+ * @param boolean $use_sub_dirs
+ */
+ public function setUseSubDirs($use_sub_dirs) {
+ $this->use_sub_dirs = $use_sub_dirs;
+ }
+
+ /**
+ * @param int $error_reporting
+ */
+ public function setErrorReporting($error_reporting) {
+ $this->error_reporting = $error_reporting;
+ }
+
+ /**
+ * @param boolean $escape_html
+ */
+ public function setEscapeHtml($escape_html) {
+ $this->escape_html = $escape_html;
+ }
+
+ /**
+ * Return auto_literal flag
+ *
+ * @return boolean
+ */
+ public function getAutoLiteral() {
+ return $this->auto_literal;
+ }
+
+ /**
+ * Set auto_literal flag
+ *
+ * @param boolean $auto_literal
+ */
+ public function setAutoLiteral($auto_literal = true) {
+ $this->auto_literal = $auto_literal;
+ }
+
+ /**
+ * @param boolean $force_compile
+ */
+ public function setForceCompile($force_compile) {
+ $this->force_compile = $force_compile;
+ }
+
+ /**
+ * @param boolean $merge_compiled_includes
+ */
+ public function setMergeCompiledIncludes($merge_compiled_includes) {
+ $this->merge_compiled_includes = $merge_compiled_includes;
+ }
+
+ /**
+ * Get left delimiter
+ *
+ * @return string
+ */
+ public function getLeftDelimiter() {
+ return $this->left_delimiter;
+ }
+
+ /**
+ * Set left delimiter
+ *
+ * @param string $left_delimiter
+ */
+ public function setLeftDelimiter($left_delimiter) {
+ $this->left_delimiter = $left_delimiter;
+ }
+
+ /**
+ * Get right delimiter
+ *
+ * @return string $right_delimiter
+ */
+ public function getRightDelimiter() {
+ return $this->right_delimiter;
+ }
+
+ /**
+ * Set right delimiter
+ *
+ * @param string
+ */
+ public function setRightDelimiter($right_delimiter) {
+ $this->right_delimiter = $right_delimiter;
+ }
+
+ /**
+ * @param boolean $debugging
+ */
+ public function setDebugging($debugging) {
+ $this->debugging = $debugging;
+ }
+
+ /**
+ * @param boolean $config_overwrite
+ */
+ public function setConfigOverwrite($config_overwrite) {
+ $this->config_overwrite = $config_overwrite;
+ }
+
+ /**
+ * @param boolean $config_booleanize
+ */
+ public function setConfigBooleanize($config_booleanize) {
+ $this->config_booleanize = $config_booleanize;
+ }
+
+ /**
+ * @param boolean $config_read_hidden
+ */
+ public function setConfigReadHidden($config_read_hidden) {
+ $this->config_read_hidden = $config_read_hidden;
+ }
+
+ /**
+ * @param boolean $compile_locking
+ */
+ public function setCompileLocking($compile_locking) {
+ $this->compile_locking = $compile_locking;
+ }
+
+ /**
+ * @param string $default_resource_type
+ */
+ public function setDefaultResourceType($default_resource_type) {
+ $this->default_resource_type = $default_resource_type;
+ }
+
+ /**
+ * Test install
+ *
+ * @param null $errors
+ */
+ public function testInstall(&$errors = null) {
+ \Smarty\TestInstall::testInstall($this, $errors);
+ }
+
+ /**
+ * Get Smarty object
+ *
+ * @return static
+ */
+ public function getSmarty() {
+ return $this;
+ }
+
+ /**
+ * Normalize and set directory string
+ *
+ * @param string $dirName cache_dir or compile_dir
+ * @param string $dir filepath of folder
+ */
+ private function _normalizeDir($dirName, $dir) {
+ $this->{$dirName} = $this->_realpath(rtrim($dir ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
+ }
+
+ /**
+ * Normalize template_dir or config_dir
+ *
+ * @param bool $isConfig true for config_dir
+ */
+ private function _normalizeTemplateConfig($isConfig) {
+ if ($isConfig) {
+ $processed = &$this->_processedConfigDir;
+ $dir = &$this->config_dir;
+ } else {
+ $processed = &$this->_processedTemplateDir;
+ $dir = &$this->template_dir;
+ }
+ if (!is_array($dir)) {
+ $dir = (array)$dir;
+ }
+ foreach ($dir as $k => $v) {
+ if (!isset($processed[$k])) {
+ $dir[$k] = $this->_realpath(rtrim($v ?? '', "/\\") . DIRECTORY_SEPARATOR, true);
+ $processed[$k] = true;
+ }
+ }
+
+ if ($isConfig) {
+ $this->_configDirNormalized = true;
+ $this->_joined_config_dir = join('#', $this->config_dir);
+ } else {
+ $this->_templateDirNormalized = true;
+ $this->_joined_template_dir = join('#', $this->template_dir);
+ }
+
+ }
+
+ /**
+ * Mutes errors for "undefined index", "undefined array key" and "trying to read property of null".
+ *
+ * @void
+ */
+ public function muteUndefinedOrNullWarnings(): void {
+ $this->isMutingUndefinedOrNullWarnings = true;
+ }
+
+ /**
+ * Indicates if Smarty will mute errors for "undefined index", "undefined array key" and "trying to read property of null".
+ *
+ * @return bool
+ */
+ public function isMutingUndefinedOrNullWarnings(): bool {
+ return $this->isMutingUndefinedOrNullWarnings;
+ }
+
+ /**
+ * Empty cache for a specific template
+ *
+ * @param string $template_name template name
+ * @param string $cache_id cache id
+ * @param string $compile_id compile id
+ * @param integer $exp_time expiration time
+ * @param string $type resource type
+ *
+ * @return int number of cache files deleted
+ * @throws \Smarty\Exception
+ *
+ * @api Smarty::clearCache()
+ */
+ public function clearCache(
+ $template_name,
+ $cache_id = null,
+ $compile_id = null,
+ $exp_time = null
+ ) {
+ return $this->getCacheResource()->clear($this, $template_name, $cache_id, $compile_id, $exp_time);
+ }
+
+ /**
+ * Empty cache folder
+ *
+ * @param integer $exp_time expiration time
+ * @param string $type resource type
+ *
+ * @return int number of cache files deleted
+ *
+ * @api Smarty::clearAllCache()
+ */
+ public function clearAllCache($exp_time = null) {
+ return $this->getCacheResource()->clearAll($this, $exp_time);
+ }
+
+ /**
+ * Delete compiled template file
+ *
+ * @param string $resource_name template name
+ * @param string $compile_id compile id
+ * @param integer $exp_time expiration time
+ *
+ * @return int number of template files deleted
+ * @throws \Smarty\Exception
+ *
+ * @api Smarty::clearCompiledTemplate()
+ */
+ public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) {
+ $_compile_dir = $this->getCompileDir();
+ if ($_compile_dir === '/') { //We should never want to delete this!
+ return 0;
+ }
+ $_compile_id = isset($compile_id) ? preg_replace('![^\w]+!', '_', $compile_id) : null;
+ $_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
+ if (isset($resource_name)) {
+ $_save_stat = $this->caching;
+ $this->caching = \Smarty\Smarty::CACHING_OFF;
+ /* @var Template $tpl */
+ $tpl = $this->doCreateTemplate($resource_name);
+ $this->caching = $_save_stat;
+ if (!$tpl->getSource()->handler->recompiled && $tpl->getSource()->exists) {
+ $_resource_part_1 = basename(str_replace('^', DIRECTORY_SEPARATOR, $tpl->getCompiled()->filepath));
+ $_resource_part_1_length = strlen($_resource_part_1);
+ } else {
+ return 0;
+ }
+ $_resource_part_2 = str_replace('.php', '.cache.php', $_resource_part_1);
+ $_resource_part_2_length = strlen($_resource_part_2);
+ }
+ $_dir = $_compile_dir;
+ if ($this->use_sub_dirs && isset($_compile_id)) {
+ $_dir .= $_compile_id . $_dir_sep;
+ }
+ if (isset($_compile_id)) {
+ $_compile_id_part = $_compile_dir . $_compile_id . $_dir_sep;
+ $_compile_id_part_length = strlen($_compile_id_part);
+ }
+ $_count = 0;
+ try {
+ $_compileDirs = new RecursiveDirectoryIterator($_dir);
+ } catch (\UnexpectedValueException $e) {
+ // path not found / not a dir
+ return 0;
+ }
+ $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST);
+ foreach ($_compile as $_file) {
+ if (substr(basename($_file->getPathname()), 0, 1) === '.') {
+ continue;
+ }
+ $_filepath = (string)$_file;
+ if ($_file->isDir()) {
+ if (!$_compile->isDot()) {
+ // delete folder if empty
+ @rmdir($_file->getPathname());
+ }
+ } else {
+ // delete only php files
+ if (substr($_filepath, -4) !== '.php') {
+ continue;
+ }
+ $unlink = false;
+ if ((!isset($_compile_id) ||
+ (isset($_filepath[$_compile_id_part_length]) &&
+ $a = !strncmp($_filepath, $_compile_id_part, $_compile_id_part_length)))
+ && (!isset($resource_name) || (isset($_filepath[$_resource_part_1_length])
+ && substr_compare(
+ $_filepath,
+ $_resource_part_1,
+ -$_resource_part_1_length,
+ $_resource_part_1_length
+ ) === 0) || (isset($_filepath[$_resource_part_2_length])
+ && substr_compare(
+ $_filepath,
+ $_resource_part_2,
+ -$_resource_part_2_length,
+ $_resource_part_2_length
+ ) === 0))
+ ) {
+ if (isset($exp_time)) {
+ if (is_file($_filepath) && time() - filemtime($_filepath) >= $exp_time) {
+ $unlink = true;
+ }
+ } else {
+ $unlink = true;
+ }
+ }
+ if ($unlink && is_file($_filepath) && @unlink($_filepath)) {
+ $_count++;
+ if (function_exists('opcache_invalidate')
+ && (!function_exists('ini_get') || strlen(ini_get('opcache.restrict_api')) < 1)
+ ) {
+ opcache_invalidate($_filepath, true);
+ } elseif (function_exists('apc_delete_file')) {
+ apc_delete_file($_filepath);
+ }
+ }
+ }
+ }
+ return $_count;
+ }
+
+ /**
+ * Compile all template files
+ *
+ * @param string $extension file extension
+ * @param bool $force_compile force all to recompile
+ * @param int $time_limit
+ * @param int $max_errors
+ *
+ * @return integer number of template files recompiled
+ * @api Smarty::compileAllTemplates()
+ *
+ */
+ public function compileAllTemplates(
+ $extension = '.tpl',
+ $force_compile = false,
+ $time_limit = 0,
+ $max_errors = null
+ ) {
+ return $this->compileAll($extension, $force_compile, $time_limit, $max_errors);
+ }
+
+ /**
+ * Compile all config files
+ *
+ * @param string $extension file extension
+ * @param bool $force_compile force all to recompile
+ * @param int $time_limit
+ * @param int $max_errors
+ *
+ * @return int number of template files recompiled
+ * @api Smarty::compileAllConfig()
+ *
+ */
+ public function compileAllConfig(
+ $extension = '.conf',
+ $force_compile = false,
+ $time_limit = 0,
+ $max_errors = null
+ ) {
+ return $this->compileAll($extension, $force_compile, $time_limit, $max_errors, true);
+ }
+
+ /**
+ * Compile all template or config files
+ *
+ * @param string $extension template file name extension
+ * @param bool $force_compile force all to recompile
+ * @param int $time_limit set maximum execution time
+ * @param int $max_errors set maximum allowed errors
+ * @param bool $isConfig flag true if called for config files
+ *
+ * @return int number of template files compiled
+ */
+ protected function compileAll(
+ $extension,
+ $force_compile,
+ $time_limit,
+ $max_errors,
+ $isConfig = false
+ ) {
+ // switch off time limit
+ if (function_exists('set_time_limit')) {
+ @set_time_limit($time_limit);
+ }
+ $_count = 0;
+ $_error_count = 0;
+ $sourceDir = $isConfig ? $this->getConfigDir() : $this->getTemplateDir();
+ // loop over array of source directories
+ foreach ($sourceDir as $_dir) {
+ $_dir_1 = new RecursiveDirectoryIterator(
+ $_dir,
+ defined('FilesystemIterator::FOLLOW_SYMLINKS') ?
+ FilesystemIterator::FOLLOW_SYMLINKS : 0
+ );
+ $_dir_2 = new RecursiveIteratorIterator($_dir_1);
+ foreach ($_dir_2 as $_fileinfo) {
+ $_file = $_fileinfo->getFilename();
+ if (substr(basename($_fileinfo->getPathname()), 0, 1) === '.' || strpos($_file, '.svn') !== false) {
+ continue;
+ }
+ if (substr_compare($_file, $extension, -strlen($extension)) !== 0) {
+ continue;
+ }
+ if ($_fileinfo->getPath() !== substr($_dir, 0, -1)) {
+ $_file = substr($_fileinfo->getPath(), strlen($_dir)) . DIRECTORY_SEPARATOR . $_file;
+ }
+ echo "\n", $_dir, '---', $_file;
+ flush();
+ $_start_time = microtime(true);
+ $_smarty = clone $this;
+ //
+ $_smarty->force_compile = $force_compile;
+ try {
+ $_tpl = $this->doCreateTemplate($_file);
+ $_tpl->caching = self::CACHING_OFF;
+ $_tpl->setSource(
+ $isConfig ? \Smarty\Template\Config::load($_tpl) : \Smarty\Template\Source::load($_tpl)
+ );
+ if ($_tpl->mustCompile()) {
+ $_tpl->compileTemplateSource();
+ $_count++;
+ echo ' compiled in ', microtime(true) - $_start_time, ' seconds';
+ flush();
+ } else {
+ echo ' is up to date';
+ flush();
+ }
+ } catch (\Exception $e) {
+ echo "\n ------>Error: ", $e->getMessage(), "\n";
+ $_error_count++;
+ }
+ // free memory
+ unset($_tpl);
+ if ($max_errors !== null && $_error_count === $max_errors) {
+ echo "\ntoo many errors\n";
+ exit(1);
+ }
+ }
+ }
+ echo "\n";
+ return $_count;
+ }
+
+ /**
+ * check client side cache
+ *
+ * @param \Smarty\Template\Cached $cached
+ * @param Template $_template
+ * @param string $content
+ *
+ * @throws \Exception
+ * @throws \Smarty\Exception
+ */
+ public function cacheModifiedCheck(Template\Cached $cached, Template $_template, $content) {
+ $_isCached = $_template->isCached() && !$_template->getCompiled()->getNocacheCode();
+ $_last_modified_date =
+ @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
+ if ($_isCached && $cached->timestamp <= strtotime($_last_modified_date)) {
+ switch (PHP_SAPI) {
+ case 'cgi': // php-cgi < 5.3
+ case 'cgi-fcgi': // php-cgi >= 5.3
+ case 'fpm-fcgi': // php-fpm >= 5.3.3
+ header('Status: 304 Not Modified');
+ break;
+ case 'cli':
+ if (/* ^phpunit */
+ !empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
+ ) {
+ $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified';
+ }
+ break;
+ default:
+ if (/* ^phpunit */
+ !empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
+ ) {
+ $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified';
+ } else {
+ header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
+ }
+ break;
+ }
+ } else {
+ switch (PHP_SAPI) {
+ case 'cli':
+ if (/* ^phpunit */
+ !empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
+ ) {
+ $_SERVER['SMARTY_PHPUNIT_HEADERS'][] =
+ 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $cached->timestamp) . ' GMT';
+ }
+ break;
+ default:
+ header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $cached->timestamp) . ' GMT');
+ break;
+ }
+ echo $content;
+ }
+ }
+
+ public function getModifierCallback(string $modifierName) {
+ foreach ($this->getExtensions() as $extension) {
+ if ($callback = $extension->getModifierCallback($modifierName)) {
+ return [new CallbackWrapper($modifierName, $callback), 'handle'];
+ }
+ }
+ return null;
+ }
+
+ public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface {
+ foreach ($this->getExtensions() as $extension) {
+ if ($handler = $extension->getFunctionHandler($functionName)) {
+ return $handler;
+ }
+ }
+ return null;
+ }
+
+ public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
+ foreach ($this->getExtensions() as $extension) {
+ if ($handler = $extension->getBlockHandler($blockTagName)) {
+ return $handler;
+ }
+ }
+ return null;
+ }
+
+ public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface {
+ foreach ($this->getExtensions() as $extension) {
+ if ($handler = $extension->getModifierCompiler($modifier)) {
+ return $handler;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Run pre-filters over template source
+ *
+ * @param string $source the content which shall be processed by the filters
+ * @param Template $template template object
+ *
+ * @return string the filtered source
+ */
+ public function runPreFilters($source, Template $template) {
+
+ foreach ($this->getExtensions() as $extension) {
+ /** @var \Smarty\Filter\FilterInterface $filter */
+ foreach ($extension->getPreFilters() as $filter) {
+ $source = $filter->filter($source, $template);
+ }
+ }
+
+ // return filtered output
+ return $source;
+ }
+
+ /**
+ * Run post-filters over template's compiled code
+ *
+ * @param string $code the content which shall be processed by the filters
+ * @param Template $template template object
+ *
+ * @return string the filtered code
+ */
+ public function runPostFilters($code, Template $template) {
+
+ foreach ($this->getExtensions() as $extension) {
+ /** @var \Smarty\Filter\FilterInterface $filter */
+ foreach ($extension->getPostFilters() as $filter) {
+ $code = $filter->filter($code, $template);
+ }
+ }
+
+ // return filtered output
+ return $code;
+ }
+
+ /**
+ * Run filters over template output
+ *
+ * @param string $content the content which shall be processed by the filters
+ * @param Template $template template object
+ *
+ * @return string the filtered (modified) output
+ */
+ public function runOutputFilters($content, Template $template) {
+
+ foreach ($this->getExtensions() as $extension) {
+ /** @var \Smarty\Filter\FilterInterface $filter */
+ foreach ($extension->getOutputFilters() as $filter) {
+ $content = $filter->filter($content, $template);
+ }
+ }
+
+ // return filtered output
+ return $content;
+ }
+
+ /**
+ * Writes file in a safe way to disk
+ *
+ * @param string $_filepath complete filepath
+ * @param string $_contents file content
+ *
+ * @return boolean true
+ * @throws Exception
+ */
+ public function writeFile($_filepath, $_contents) {
+ $_error_reporting = error_reporting();
+ error_reporting($_error_reporting & ~E_NOTICE & ~E_WARNING);
+ $_dirpath = dirname($_filepath);
+ // if subdirs, create dir structure
+ if ($_dirpath !== '.') {
+ $i = 0;
+ // loop if concurrency problem occurs
+ // see https://bugs.php.net/bug.php?id=35326
+ while (!is_dir($_dirpath)) {
+ if (@mkdir($_dirpath, 0777, true)) {
+ break;
+ }
+ clearstatcache();
+ if (++$i === 3) {
+ error_reporting($_error_reporting);
+ throw new Exception("unable to create directory {$_dirpath}");
+ }
+ sleep(1);
+ }
+ }
+ // write to tmp file, then move to overt file lock race condition
+ $_tmp_file = $_dirpath . DIRECTORY_SEPARATOR . str_replace(['.', ','], '_', uniqid('wrt', true));
+ if (!file_put_contents($_tmp_file, $_contents)) {
+ error_reporting($_error_reporting);
+ throw new Exception("unable to write file {$_tmp_file}");
+ }
+ /*
+ * Windows' rename() fails if the destination exists,
+ * Linux' rename() properly handles the overwrite.
+ * Simply unlink()ing a file might cause other processes
+ * currently reading that file to fail, but linux' rename()
+ * seems to be smart enough to handle that for us.
+ */
+ if (\Smarty\Smarty::$_IS_WINDOWS) {
+ // remove original file
+ if (is_file($_filepath)) {
+ @unlink($_filepath);
+ }
+ // rename tmp file
+ $success = @rename($_tmp_file, $_filepath);
+ } else {
+ // rename tmp file
+ $success = @rename($_tmp_file, $_filepath);
+ if (!$success) {
+ // remove original file
+ if (is_file($_filepath)) {
+ @unlink($_filepath);
+ }
+ // rename tmp file
+ $success = @rename($_tmp_file, $_filepath);
+ }
+ }
+ if (!$success) {
+ error_reporting($_error_reporting);
+ throw new Exception("unable to write file {$_filepath}");
+ }
+ // set file permissions
+ @chmod($_filepath, 0666 & ~umask());
+ error_reporting($_error_reporting);
+ return true;
+ }
+
+ private $runtimes = [];
+
+ /**
+ * Loads and returns a runtime extension or null if not found
+ *
+ * @param string $type
+ *
+ * @return object|null
+ */
+ public function getRuntime(string $type) {
+
+ if (isset($this->runtimes[$type])) {
+ return $this->runtimes[$type];
+ }
+
+ // Lazy load runtimes when/if needed
+ switch ($type) {
+ case 'Capture':
+ return $this->runtimes[$type] = new CaptureRuntime();
+ case 'Foreach':
+ return $this->runtimes[$type] = new ForeachRuntime();
+ case 'Inheritance':
+ return $this->runtimes[$type] = new InheritanceRuntime();
+ case 'TplFunction':
+ return $this->runtimes[$type] = new TplFunctionRuntime();
+ case 'DefaultPluginHandler':
+ return $this->runtimes[$type] = new DefaultPluginHandlerRuntime(
+ $this->getDefaultPluginHandlerFunc()
+ );
+ }
+
+ throw new \Smarty\Exception('Trying to load invalid runtime ' . $type);
+ }
+
+ /**
+ * Indicates if a runtime is available.
+ *
+ * @param string $type
+ *
+ * @return bool
+ */
+ public function hasRuntime(string $type): bool {
+ try {
+ $this->getRuntime($type);
+ return true;
+ } catch (\Smarty\Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * @return callable|null
+ */
+ public function getDefaultPluginHandlerFunc(): ?callable {
+ return $this->default_plugin_handler_func;
+ }
+
+ /**
+ * load a filter of specified type and name
+ *
+ * @param string $type filter type
+ * @param string $name filter name
+ *
+ * @return bool
+ * @throws \Smarty\Exception
+ * @api Smarty::loadFilter()
+ *
+ * @deprecated since 5.0
+ */
+ public function loadFilter($type, $name) {
+
+ if ($type == \Smarty\Smarty::FILTER_VARIABLE) {
+ foreach ($this->getExtensions() as $extension) {
+ if ($extension->getModifierCallback($name)) {
+
+ trigger_error('Using Smarty::loadFilter() to load variable filters is deprecated and will ' .
+ 'be removed in a future release. Use Smarty::addDefaultModifiers() to add a modifier.',
+ E_USER_DEPRECATED);
+
+ $this->addDefaultModifiers([$name]);
+ return true;
+ }
+ }
+ }
+
+ trigger_error('Using Smarty::loadFilter() to load filters is deprecated and will be ' .
+ 'removed in a future release. Use Smarty::addExtension() to add an extension or Smarty::registerFilter to ' .
+ 'quickly register a filter using a callback function.', E_USER_DEPRECATED);
+
+ if ($type == \Smarty\Smarty::FILTER_OUTPUT && $name == 'trimwhitespace') {
+ $this->BCPluginsAdapter->addOutputFilter(new TrimWhitespace());
+ return true;
+ }
+
+ $_plugin = "smarty_{$type}filter_{$name}";
+ if (!is_callable($_plugin) && class_exists($_plugin, false)) {
+ $_plugin = [$_plugin, 'execute'];
+ }
+
+ if (is_callable($_plugin)) {
+ $this->registerFilter($type, $_plugin, $name);
+ return true;
+ }
+
+ throw new Exception("{$type}filter '{$name}' not found or callable");
+ }
+
+ /**
+ * load a filter of specified type and name
+ *
+ * @param string $type filter type
+ * @param string $name filter name
+ *
+ * @return static
+ * @throws \Smarty\Exception
+ * @api Smarty::unloadFilter()
+ *
+ *
+ * @deprecated since 5.0
+ */
+ public function unloadFilter($type, $name) {
+ trigger_error('Using Smarty::unloadFilter() to unload filters is deprecated and will be ' .
+ 'removed in a future release. Use Smarty::addExtension() to add an extension or Smarty::(un)registerFilter to ' .
+ 'quickly (un)register a filter using a callback function.', E_USER_DEPRECATED);
+
+ return $this->unregisterFilter($type, $name);
+ }
+
+ private $_caching_type = 'file';
+
+ /**
+ * @param $type
+ *
+ * @return void
+ * @deprecated since 5.0
+ */
+ public function setCachingType($type) {
+ trigger_error('Using Smarty::setCachingType() is deprecated and will be ' .
+ 'removed in a future release. Use Smarty::setCacheResource() instead.', E_USER_DEPRECATED);
+ $this->_caching_type = $type;
+ $this->activateBCCacheResource();
+ }
+
+ /**
+ * @return string
+ * @deprecated since 5.0
+ */
+ public function getCachingType(): string {
+ trigger_error('Using Smarty::getCachingType() is deprecated and will be ' .
+ 'removed in a future release.', E_USER_DEPRECATED);
+ return $this->_caching_type;
+ }
+
+ /**
+ * Registers a resource to fetch a template
+ *
+ * @param string $name name of resource type
+ * @param Base $resource_handler
+ *
+ * @return static
+ *
+ * @api Smarty::registerCacheResource()
+ *
+ * @deprecated since 5.0
+ */
+ public function registerCacheResource($name, \Smarty\Cacheresource\Base $resource_handler) {
+
+ trigger_error('Using Smarty::registerCacheResource() is deprecated and will be ' .
+ 'removed in a future release. Use Smarty::setCacheResource() instead.', E_USER_DEPRECATED);
+
+ $this->registered_cache_resources[$name] = $resource_handler;
+ $this->activateBCCacheResource();
+ return $this;
+ }
+
+ /**
+ * Unregisters a resource to fetch a template
+ *
+ * @param $name
+ *
+ * @return static
+ * @api Smarty::unregisterCacheResource()
+ *
+ * @deprecated since 5.0
+ *
+ */
+ public function unregisterCacheResource($name) {
+
+ trigger_error('Using Smarty::unregisterCacheResource() is deprecated and will be ' .
+ 'removed in a future release.', E_USER_DEPRECATED);
+
+ if (isset($this->registered_cache_resources[$name])) {
+ unset($this->registered_cache_resources[$name]);
+ }
+ return $this;
+ }
+
+ private function activateBCCacheResource() {
+ if ($this->_caching_type == 'file') {
+ $this->setCacheResource(new File());
+ }
+ if (isset($this->registered_cache_resources[$this->_caching_type])) {
+ $this->setCacheResource($this->registered_cache_resources[$this->_caching_type]);
+ }
+ }
+
+ /**
+ * Registers a filter function
+ *
+ * @param string $type filter type
+ * @param callable $callback
+ * @param string|null $name optional filter name
+ *
+ * @return static
+ * @throws \Smarty\Exception
+ *
+ * @api Smarty::registerFilter()
+ */
+ public function registerFilter($type, $callback, $name = null) {
+ $name = $name ?? $this->_getFilterName($callback);
+ if (!is_callable($callback)) {
+ throw new Exception("{$type}filter '{$name}' not callable");
+ }
+ switch ($type) {
+ case 'variable':
+ $this->registerPlugin(self::PLUGIN_MODIFIER, $name, $callback);
+ trigger_error('Using Smarty::registerFilter() to register variable filters is deprecated and ' .
+ 'will be removed in a future release. Use Smarty::addDefaultModifiers() to add a modifier.',
+ E_USER_DEPRECATED);
+
+ $this->addDefaultModifiers([$name]);
+ break;
+ case 'output':
+ $this->BCPluginsAdapter->addCallableAsOutputFilter($callback, $name);
+ break;
+ case 'pre':
+ $this->BCPluginsAdapter->addCallableAsPreFilter($callback, $name);
+ break;
+ case 'post':
+ $this->BCPluginsAdapter->addCallableAsPostFilter($callback, $name);
+ break;
+ default:
+ throw new Exception("Illegal filter type '{$type}'");
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return internal filter name
+ *
+ * @param callback $callable
+ *
+ * @return string|null internal filter name or null if callable cannot be serialized
+ */
+ private function _getFilterName($callable) {
+ if (is_array($callable)) {
+ $_class_name = is_object($callable[0]) ? get_class($callable[0]) : $callable[0];
+ return $_class_name . '_' . $callable[1];
+ } elseif (is_string($callable)) {
+ return $callable;
+ }
+ return null;
+ }
+
+ /**
+ * Unregisters a filter function. Smarty cannot unregister closures/anonymous functions if
+ * no name was given in ::registerFilter.
+ *
+ * @param string $type filter type
+ * @param callback|string $name the name previously used in ::registerFilter
+ *
+ * @return static
+ * @throws \Smarty\Exception
+ * @api Smarty::unregisterFilter()
+ *
+ *
+ */
+ public function unregisterFilter($type, $name) {
+
+ if (!is_string($name)) {
+ $name = $this->_getFilterName($name);
+ }
+
+ if ($name) {
+ switch ($type) {
+ case 'output':
+ $this->BCPluginsAdapter->removeOutputFilter($name);
+ break;
+ case 'pre':
+ $this->BCPluginsAdapter->removePreFilter($name);
+ break;
+ case 'post':
+ $this->BCPluginsAdapter->removePostFilter($name);
+ break;
+ default:
+ throw new Exception("Illegal filter type '{$type}'");
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add default modifiers
+ *
+ * @param array|string $modifiers modifier or list of modifiers
+ * to add
+ *
+ * @return static
+ * @api Smarty::addDefaultModifiers()
+ *
+ */
+ public function addDefaultModifiers($modifiers) {
+ if (is_array($modifiers)) {
+ $this->default_modifiers = array_merge($this->default_modifiers, $modifiers);
+ } else {
+ $this->default_modifiers[] = $modifiers;
+ }
+ return $this;
+ }
+
+ /**
+ * Get default modifiers
+ *
+ * @return array list of default modifiers
+ * @api Smarty::getDefaultModifiers()
+ *
+ */
+ public function getDefaultModifiers() {
+ return $this->default_modifiers;
+ }
+
+ /**
+ * Set default modifiers
+ *
+ * @param array|string $modifiers modifier or list of modifiers
+ * to set
+ *
+ * @return static
+ * @api Smarty::setDefaultModifiers()
+ *
+ */
+ public function setDefaultModifiers($modifiers) {
+ $this->default_modifiers = (array)$modifiers;
+ return $this;
+ }
+
+ /**
+ * @return Cacheresource\Base
+ */
+ public function getCacheResource(): Cacheresource\Base {
+ return $this->cacheResource;
+ }
+
+ /**
+ * @param Cacheresource\Base $cacheResource
+ */
+ public function setCacheResource(Cacheresource\Base $cacheResource): void {
+ $this->cacheResource = $cacheResource;
+ }
+
+ /**
+ * fetches a rendered Smarty template
+ *
+ * @param string $template the resource handle of the template file or template object
+ * @param mixed $cache_id cache id to be used with this template
+ * @param mixed $compile_id compile id to be used with this template
+ *
+ * @return string rendered template output
+ * @throws Exception
+ * @throws Exception
+ */
+ public function fetch($template = null, $cache_id = null, $compile_id = null) {
+ return $this->returnOrCreateTemplate($template, $cache_id, $compile_id)->fetch();
+ }
+
+ /**
+ * displays a Smarty template
+ *
+ * @param string $template the resource handle of the template file or template object
+ * @param mixed $cache_id cache id to be used with this template
+ * @param mixed $compile_id compile id to be used with this template
+ *
+ * @throws \Exception
+ * @throws \Smarty\Exception
+ */
+ public function display($template = null, $cache_id = null, $compile_id = null) {
+ $this->returnOrCreateTemplate($template, $cache_id, $compile_id)->display();
+ }
+
+ /**
+ * @param $resource_name
+ * @param $cache_id
+ * @param $compile_id
+ * @param $parent
+ * @param $caching
+ * @param $cache_lifetime
+ * @param bool $isConfig
+ * @param array $data
+ *
+ * @return Template
+ * @throws Exception
+ */
+ public function doCreateTemplate(
+ $resource_name,
+ $cache_id = null,
+ $compile_id = null,
+ $parent = null,
+ $caching = null,
+ $cache_lifetime = null,
+ bool $isConfig = false,
+ array $data = []): Template {
+
+ if (!$this->_templateDirNormalized) {
+ $this->_normalizeTemplateConfig(false);
+ }
+
+ $_templateId = $this->generateUniqueTemplateId($resource_name, $cache_id, $compile_id, $caching);
+
+ if (!isset($this->templates[$_templateId])) {
+ $newTemplate = new Template($resource_name, $this, $parent ?: $this, $cache_id, $compile_id, $caching, $isConfig);
+ $newTemplate->templateId = $_templateId; // @TODO this could go in constructor ^?
+ $this->templates[$_templateId] = $newTemplate;
+ }
+
+ $tpl = clone $this->templates[$_templateId];
+
+ $tpl->setParent($parent ?: $this);
+
+ if ($cache_lifetime) {
+ $tpl->setCacheLifetime($cache_lifetime);
+ }
+
+ // fill data if present
+ foreach ($data as $_key => $_val) {
+ $tpl->assign($_key, $_val);
+ }
+
+ $tpl->tplFunctions = array_merge($parent->tplFunctions ?? [], $tpl->tplFunctions ?? []);
+
+ if (!$this->debugging && $this->debugging_ctrl === 'URL') {
+ $tpl->getSmarty()->getDebug()->debugUrl($tpl->getSmarty());
+ }
+ return $tpl;
+ }
+
+ /**
+ * test if cache is valid
+ *
+ * @param null|string|Template $template the resource handle of the template file or template
+ * object
+ * @param mixed $cache_id cache id to be used with this template
+ * @param mixed $compile_id compile id to be used with this template
+ *
+ * @return bool cache status
+ * @throws \Exception
+ * @throws \Smarty\Exception
+ *
+ * @api Smarty::isCached()
+ */
+ public function isCached($template = null, $cache_id = null, $compile_id = null) {
+ return $this->returnOrCreateTemplate($template, $cache_id, $compile_id)->isCached();
+ }
+
+ /**
+ * @param $template
+ * @param $cache_id
+ * @param $compile_id
+ * @param $parent
+ *
+ * @return Template
+ * @throws Exception
+ */
+ private function returnOrCreateTemplate($template, $cache_id = null, $compile_id = null) {
+ if (!($template instanceof Template)) {
+ $template = $this->createTemplate($template, $cache_id, $compile_id, $this);
+ $template->caching = $this->caching;
+ }
+ return $template;
+ }
+
+ /**
+ * Sets if Smarty should check If-Modified-Since headers to determine cache validity.
+ * @param bool $cache_modified_check
+ * @return void
+ */
+ public function setCacheModifiedCheck($cache_modified_check): void {
+ $this->cache_modified_check = (bool) $cache_modified_check;
+ }
+
+}
+
diff --git a/src/includes/smarty-5.4.1/src/Template.php b/src/includes/smarty-5.4.1/src/Template.php
new file mode 100644
index 0000000..fcb0f58
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Template.php
@@ -0,0 +1,732 @@
+getSmarty()-getLeftDelimiter().
+ *
+ * @var string
+ */
+ private $left_delimiter = null;
+
+ /**
+ * Template right-delimiter. If null, defaults to $this->getSmarty()-getRightDelimiter().
+ *
+ * @var string
+ */
+ private $right_delimiter = null;
+
+ /**
+ * @var InheritanceRuntime|null
+ */
+ private $inheritance;
+
+ /**
+ * Create template data object
+ * Some of the global Smarty settings copied to template scope
+ * It load the required template resources and caching plugins
+ *
+ * @param string $template_resource template resource string
+ * @param Smarty $smarty Smarty instance
+ * @param \Smarty\Data|null $_parent back pointer to parent object with variables or null
+ * @param mixed $_cache_id cache id or null
+ * @param mixed $_compile_id compile id or null
+ * @param bool|int|null $_caching use caching?
+ * @param bool $_isConfig
+ *
+ * @throws \Smarty\Exception
+ */
+ public function __construct(
+ $template_resource,
+ Smarty $smarty,
+ \Smarty\Data $_parent = null,
+ $_cache_id = null,
+ $_compile_id = null,
+ $_caching = null,
+ $_isConfig = false
+ ) {
+ $this->smarty = $smarty;
+ // Smarty parameter
+ $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id;
+ $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id;
+ $this->caching = (int)($_caching === null ? $this->smarty->caching : $_caching);
+ $this->cache_lifetime = $this->smarty->cache_lifetime;
+ $this->compile_check = (int)$smarty->compile_check;
+ $this->parent = $_parent;
+ // Template resource
+ $this->template_resource = $template_resource;
+
+ $this->source = $_isConfig ? Config::load($this) : Source::load($this);
+ $this->compiled = Compiled::load($this);
+
+ if ($smarty->security_policy) {
+ $smarty->security_policy->registerCallBacks($this);
+ }
+ }
+
+ /**
+ * render template
+ *
+ * @param bool $no_output_filter if true do not run output filter
+ * @param null|bool $display true: display, false: fetch null: sub-template
+ *
+ * @return string
+ * @throws \Exception
+ * @throws \Smarty\Exception
+ */
+ private function render($no_output_filter = true, $display = null) {
+ if ($this->smarty->debugging) {
+ $this->smarty->getDebug()->start_template($this, $display);
+ }
+ // checks if template exists
+ if ($this->compile_check && !$this->getSource()->exists) {
+ throw new Exception(
+ "Unable to load '{$this->getSource()->type}:{$this->getSource()->name}'" .
+ ($this->_isSubTpl() ? " in '{$this->parent->template_resource}'" : '')
+ );
+ }
+
+ // disable caching for evaluated code
+ if ($this->getSource()->handler->recompiled) {
+ $this->caching = \Smarty\Smarty::CACHING_OFF;
+ }
+
+ foreach ($this->startRenderCallbacks as $callback) {
+ call_user_func($callback, $this);
+ }
+
+ try {
+
+ // read from cache or render
+ if ($this->caching === \Smarty\Smarty::CACHING_LIFETIME_CURRENT || $this->caching === \Smarty\Smarty::CACHING_LIFETIME_SAVED) {
+ $this->getCached()->render($this, $no_output_filter);
+ } else {
+ $this->getCompiled()->render($this);
+ }
+
+ } finally {
+ foreach ($this->endRenderCallbacks as $callback) {
+ call_user_func($callback, $this);
+ }
+ }
+
+ // display or fetch
+ if ($display) {
+ if ($this->caching && $this->smarty->cache_modified_check) {
+ $this->smarty->cacheModifiedCheck(
+ $this->getCached(),
+ $this,
+ isset($content) ? $content : ob_get_clean()
+ );
+ } else {
+ if ((!$this->caching || $this->getCached()->getNocacheCode() || $this->getSource()->handler->recompiled)
+ && !$no_output_filter
+ ) {
+ echo $this->smarty->runOutputFilters(ob_get_clean(), $this);
+ } else {
+ echo ob_get_clean();
+ }
+ }
+ if ($this->smarty->debugging) {
+ $this->smarty->getDebug()->end_template($this);
+ // debug output
+ $this->smarty->getDebug()->display_debug($this, true);
+ }
+ return '';
+ } else {
+ if ($this->smarty->debugging) {
+ $this->smarty->getDebug()->end_template($this);
+ if ($this->smarty->debugging === 2 && $display === false) {
+ $this->smarty->getDebug()->display_debug($this, true);
+ }
+ }
+ if (
+ !$no_output_filter
+ && (!$this->caching || $this->getCached()->getNocacheCode() || $this->getSource()->handler->recompiled)
+ ) {
+
+ return $this->smarty->runOutputFilters(ob_get_clean(), $this);
+ }
+ // return cache content
+ return null;
+ }
+ }
+
+ /**
+ * Runtime function to render sub-template
+ *
+ * @param string $template_name template name
+ * @param mixed $cache_id cache id
+ * @param mixed $compile_id compile id
+ * @param integer $caching cache mode
+ * @param integer $cache_lifetime lifetime of cache data
+ * @param array $extra_vars passed parameter template variables
+ * @param int|null $scope
+ *
+ * @throws Exception
+ */
+ public function renderSubTemplate(
+ $template_name,
+ $cache_id,
+ $compile_id,
+ $caching,
+ $cache_lifetime,
+ array $extra_vars = [],
+ int $scope = null,
+ ?string $currentDir = null
+ ) {
+
+ $name = $this->parseResourceName($template_name);
+ if ($currentDir && preg_match('/^\.{1,2}\//', $name)) {
+ // relative template resource name, append it to current template name
+ $template_name = $currentDir . DIRECTORY_SEPARATOR . $name;
+ }
+
+ $tpl = $this->smarty->doCreateTemplate($template_name, $cache_id, $compile_id, $this, $caching, $cache_lifetime);
+
+ $tpl->inheritance = $this->getInheritance(); // re-use the same Inheritance object inside the inheritance tree
+
+ if ($scope) {
+ $tpl->defaultScope = $scope;
+ }
+
+ if ($caching) {
+ if ($tpl->templateId !== $this->templateId && $caching !== \Smarty\Template::CACHING_NOCACHE_CODE) {
+ $tpl->getCached(true);
+ } else {
+ // re-use the same Cache object across subtemplates to gather hashes and file dependencies.
+ $tpl->setCached($this->getCached());
+ }
+ }
+
+ foreach ($extra_vars as $_key => $_val) {
+ $tpl->assign($_key, $_val);
+ }
+ if ($tpl->caching === \Smarty\Template::CACHING_NOCACHE_CODE) {
+ if ($tpl->getCompiled()->getNocacheCode()) {
+ $this->getCached()->hashes[$tpl->getCompiled()->nocache_hash] = true;
+ }
+ }
+
+ $tpl->render();
+ }
+
+ /**
+ * Remove type indicator from resource name if present.
+ * E.g. $this->parseResourceName('file:template.tpl') returns 'template.tpl'
+ *
+ * @note "C:/foo.tpl" was forced to file resource up till Smarty 3.1.3 (including).
+ *
+ * @param string $resource_name template_resource or config_resource to parse
+ *
+ * @return string
+ */
+ private function parseResourceName($resource_name): string {
+ if (preg_match('/^([A-Za-z0-9_\-]{2,}):/', $resource_name, $match)) {
+ return substr($resource_name, strlen($match[0]));
+ }
+ return $resource_name;
+ }
+
+ /**
+ * Check if this is a sub template
+ *
+ * @return bool true is sub template
+ */
+ public function _isSubTpl() {
+ return isset($this->parent) && $this->parent instanceof Template;
+ }
+
+ public function assign($tpl_var, $value = null, $nocache = false, $scope = null) {
+ return parent::assign($tpl_var, $value, $nocache, $scope);
+ }
+
+ /**
+ * Compiles the template
+ * If the template is not evaluated the compiled template is saved on disk
+ *
+ * @TODO only used in compileAll and 1 unit test: can we move this and make compileAndWrite private?
+ *
+ * @throws \Exception
+ */
+ public function compileTemplateSource() {
+ return $this->getCompiled()->compileAndWrite($this);
+ }
+
+ /**
+ * Return cached content
+ *
+ * @return null|string
+ * @throws Exception
+ */
+ public function getCachedContent() {
+ return $this->getCached()->getContent($this);
+ }
+
+ /**
+ * Writes the content to cache resource
+ *
+ * @param string $content
+ *
+ * @return bool
+ *
+ * @TODO this method is only used in unit tests that (mostly) try to test CacheResources.
+ */
+ public function writeCachedContent($content) {
+ if ($this->getSource()->handler->recompiled || !$this->caching
+ ) {
+ // don't write cache file
+ return false;
+ }
+ $codeframe = $this->createCodeFrame($content, '', true);
+ return $this->getCached()->writeCache($this, $codeframe);
+ }
+
+ /**
+ * Get unique template id
+ *
+ * @return string
+ */
+ public function getTemplateId() {
+ return $this->templateId;
+ }
+
+ /**
+ * runtime error not matching capture tags
+ *
+ * @throws \Smarty\Exception
+ */
+ public function capture_error() {
+ throw new Exception("Not matching {capture} open/close in '{$this->template_resource}'");
+ }
+
+ /**
+ * Return Compiled object
+ *
+ * @param bool $forceNew force new compiled object
+ */
+ public function getCompiled($forceNew = false) {
+ if ($forceNew || !isset($this->compiled)) {
+ $this->compiled = Compiled::load($this);
+ }
+ return $this->compiled;
+ }
+
+ /**
+ * Return Cached object
+ *
+ * @param bool $forceNew force new cached object
+ *
+ * @throws Exception
+ */
+ public function getCached($forceNew = false): Cached {
+ if ($forceNew || !isset($this->cached)) {
+ $cacheResource = $this->smarty->getCacheResource();
+ $this->cached = new Cached(
+ $this->source,
+ $cacheResource,
+ $this->compile_id,
+ $this->cache_id
+ );
+ if ($this->isCachingEnabled()) {
+ $cacheResource->populate($this->cached, $this);
+ } else {
+ $this->cached->setValid(false);
+ }
+ }
+ return $this->cached;
+ }
+
+ private function isCachingEnabled(): bool {
+ return $this->caching && !$this->getSource()->handler->recompiled;
+ }
+
+ /**
+ * Helper function for InheritanceRuntime object
+ *
+ * @return InheritanceRuntime
+ * @throws Exception
+ */
+ public function getInheritance(): InheritanceRuntime {
+ if (is_null($this->inheritance)) {
+ $this->inheritance = clone $this->getSmarty()->getRuntime('Inheritance');
+ }
+ return $this->inheritance;
+ }
+
+ /**
+ * Sets a new InheritanceRuntime object.
+ *
+ * @param InheritanceRuntime $inheritanceRuntime
+ *
+ * @return void
+ */
+ public function setInheritance(InheritanceRuntime $inheritanceRuntime) {
+ $this->inheritance = $inheritanceRuntime;
+ }
+
+ /**
+ * Return Compiler object
+ */
+ public function getCompiler() {
+ if (!isset($this->compiler)) {
+ $this->compiler = $this->getSource()->createCompiler();
+ }
+ return $this->compiler;
+ }
+
+ /**
+ * Create code frame for compiled and cached templates
+ *
+ * @param string $content optional template content
+ * @param string $functions compiled template function and block code
+ * @param bool $cache flag for cache file
+ * @param Compiler\Template|null $compiler
+ *
+ * @return string
+ * @throws Exception
+ */
+ public function createCodeFrame($content = '', $functions = '', $cache = false, \Smarty\Compiler\Template $compiler = null) {
+ return $this->getCodeFrameCompiler()->create($content, $functions, $cache, $compiler);
+ }
+
+ /**
+ * Template data object destructor
+ */
+ public function __destruct() {
+ if ($this->smarty->cache_locking && $this->getCached()->is_locked) {
+ $this->getCached()->handler->releaseLock($this->smarty, $this->getCached());
+ }
+ }
+
+ /**
+ * Returns if the current template must be compiled by the Smarty compiler
+ * It does compare the timestamps of template source and the compiled templates and checks the force compile
+ * configuration
+ *
+ * @return bool
+ * @throws \Smarty\Exception
+ */
+ public function mustCompile(): bool {
+ if (!$this->getSource()->exists) {
+ if ($this->_isSubTpl()) {
+ $parent_resource = " in '{$this->parent->template_resource}'";
+ } else {
+ $parent_resource = '';
+ }
+ throw new Exception("Unable to load {$this->getSource()->type} '{$this->getSource()->name}'{$parent_resource}");
+ }
+
+ // @TODO move this logic to Compiled
+ return $this->smarty->force_compile
+ || $this->getSource()->handler->recompiled
+ || !$this->getCompiled()->exists
+ || ($this->compile_check && $this->getCompiled()->getTimeStamp() < $this->getSource()->getTimeStamp());
+ }
+
+ private function getCodeFrameCompiler(): Compiler\CodeFrame {
+ return new \Smarty\Compiler\CodeFrame($this);
+ }
+
+ /**
+ * Get left delimiter
+ *
+ * @return string
+ */
+ public function getLeftDelimiter()
+ {
+ return $this->left_delimiter ?? $this->getSmarty()->getLeftDelimiter();
+ }
+
+ /**
+ * Set left delimiter
+ *
+ * @param string $left_delimiter
+ */
+ public function setLeftDelimiter($left_delimiter)
+ {
+ $this->left_delimiter = $left_delimiter;
+ }
+
+ /**
+ * Get right delimiter
+ *
+ * @return string $right_delimiter
+ */
+ public function getRightDelimiter()
+ {
+ return $this->right_delimiter ?? $this->getSmarty()->getRightDelimiter();;
+ }
+
+ /**
+ * Set right delimiter
+ *
+ * @param string
+ */
+ public function setRightDelimiter($right_delimiter)
+ {
+ $this->right_delimiter = $right_delimiter;
+ }
+
+ /**
+ * gets a stream variable
+ *
+ * @param string $variable the stream of the variable
+ *
+ * @return mixed
+ * @throws \Smarty\Exception
+ *
+ */
+ public function getStreamVariable($variable)
+ {
+
+ trigger_error("Using stream variables (\`\{\$foo:bar\}\`)is deprecated.", E_USER_DEPRECATED);
+
+ $_result = '';
+ $fp = fopen($variable, 'r+');
+ if ($fp) {
+ while (!feof($fp) && ($current_line = fgets($fp)) !== false) {
+ $_result .= $current_line;
+ }
+ fclose($fp);
+ return $_result;
+ }
+ if ($this->getSmarty()->error_unassigned) {
+ throw new Exception('Undefined stream variable "' . $variable . '"');
+ }
+ return null;
+ }
+ /**
+ * @inheritdoc
+ */
+ public function configLoad($config_file, $sections = null)
+ {
+ $confObj = parent::configLoad($config_file, $sections);
+
+ $this->getCompiled()->file_dependency[ $confObj->getSource()->uid ] =
+ array($confObj->getSource()->getResourceName(), $confObj->getSource()->getTimeStamp(), $confObj->getSource()->type);
+
+ return $confObj;
+ }
+
+ public function fetch() {
+ $result = $this->_execute(0);
+ return $result === null ? ob_get_clean() : $result;
+ }
+
+ public function display() {
+ $this->_execute(1);
+ }
+
+ /**
+ * test if cache is valid
+ *
+ * @param mixed $cache_id cache id to be used with this template
+ * @param mixed $compile_id compile id to be used with this template
+ * @param object $parent next higher level of Smarty variables
+ *
+ * @return bool cache status
+ * @throws \Exception
+ * @throws \Smarty\Exception
+ *
+ * @api Smarty::isCached()
+ */
+ public function isCached(): bool {
+ return (bool) $this->_execute(2);
+ }
+
+ /**
+ * fetches a rendered Smarty template
+ *
+ * @param string $function function type 0 = fetch, 1 = display, 2 = isCache
+ *
+ * @return mixed
+ * @throws Exception
+ * @throws \Throwable
+ */
+ private function _execute($function) {
+
+ $smarty = $this->getSmarty();
+
+ // make sure we have integer values
+ $this->caching = (int)$this->caching;
+ // fetch template content
+ $level = ob_get_level();
+ try {
+ $_smarty_old_error_level =
+ isset($smarty->error_reporting) ? error_reporting($smarty->error_reporting) : null;
+
+ if ($smarty->isMutingUndefinedOrNullWarnings()) {
+ $errorHandler = new \Smarty\ErrorHandler();
+ $errorHandler->activate();
+ }
+
+ if ($function === 2) {
+ if ($this->caching) {
+ // return cache status of template
+ $result = $this->getCached()->isCached($this);
+ } else {
+ return false;
+ }
+ } else {
+
+ // After rendering a template, the tpl/config variables are reset, so the template can be re-used.
+ $this->pushStack();
+
+ // Start output-buffering.
+ ob_start();
+
+ $result = $this->render(false, $function);
+
+ // Restore the template to its previous state
+ $this->popStack();
+ }
+
+ if (isset($errorHandler)) {
+ $errorHandler->deactivate();
+ }
+
+ if (isset($_smarty_old_error_level)) {
+ error_reporting($_smarty_old_error_level);
+ }
+ return $result;
+ } catch (\Throwable $e) {
+ while (ob_get_level() > $level) {
+ ob_end_clean();
+ }
+ if (isset($errorHandler)) {
+ $errorHandler->deactivate();
+ }
+
+ if (isset($_smarty_old_error_level)) {
+ error_reporting($_smarty_old_error_level);
+ }
+ throw $e;
+ }
+ }
+
+ /**
+ * @return Config|Source|null
+ */
+ public function getSource() {
+ return $this->source;
+ }
+
+ /**
+ * @param Config|Source|null $source
+ */
+ public function setSource($source): void {
+ $this->source = $source;
+ }
+
+ /**
+ * Sets the Cached object, so subtemplates can share one Cached object to gather meta-data.
+ *
+ * @param Cached $cached
+ *
+ * @return void
+ */
+ private function setCached(Cached $cached) {
+ $this->cached = $cached;
+ }
+
+ /**
+ * @param string $compile_id
+ *
+ * @throws Exception
+ */
+ public function setCompileId($compile_id) {
+ parent::setCompileId($compile_id);
+ $this->getCompiled(true);
+ if ($this->caching) {
+ $this->getCached(true);
+ }
+ }
+
+ /**
+ * @param string $cache_id
+ *
+ * @throws Exception
+ */
+ public function setCacheId($cache_id) {
+ parent::setCacheId($cache_id);
+ $this->getCached(true);
+ }
+
+}
diff --git a/src/includes/smarty-5.4.1/src/Template/Cached.php b/src/includes/smarty-5.4.1/src/Template/Cached.php
new file mode 100644
index 0000000..78635db
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/Template/Cached.php
@@ -0,0 +1,428 @@
+valid = $valid;
+ }
+
+ /**
+ * CacheResource Handler
+ *
+ * @var \Smarty\Cacheresource\Base
+ */
+ public $handler = null;
+
+ /**
+ * Template Cache Id (\Smarty\Template::$cache_id)
+ *
+ * @var string
+ */
+ public $cache_id = null;
+
+ /**
+ * saved cache lifetime in seconds
+ *
+ * @var int
+ */
+ public $cache_lifetime = 0;
+
+ /**
+ * Id for cache locking
+ *
+ * @var string
+ */
+ public $lock_id = null;
+
+ /**
+ * flag that cache is locked by this instance
+ *
+ * @var bool
+ */
+ public $is_locked = false;
+
+ /**
+ * Source Object
+ *
+ * @var Source
+ */
+ public $source = null;
+
+ /**
+ * Nocache hash codes of processed compiled templates
+ *
+ * @var array
+ */
+ public $hashes = [];
+
+ /**
+ * Content buffer
+ *
+ * @var string
+ */
+ public $content = null;
+
+ /**
+ * create Cached Object container
+ *
+ * @param Source $source
+ * @param \Smarty\Cacheresource\Base $handler
+ * @param $compile_id
+ * @param $cache_id
+ */
+ public function __construct(Source $source, \Smarty\Cacheresource\Base $handler, $compile_id, $cache_id) {
+ $this->compile_id = $compile_id;
+ $this->cache_id = $cache_id;
+ $this->source = $source;
+ $this->handler = $handler;
+ }
+
+ /**
+ * Render cache template
+ *
+ * @param \Smarty\Template $_template
+ * @param bool $no_output_filter
+ *
+ * @throws \Exception
+ */
+ public function render(Template $_template, $no_output_filter = true) {
+
+ if (!$this->isCached($_template)) {
+ $this->updateCache($_template, $no_output_filter);
+ } else {
+ if (!$this->processed) {
+ $this->process($_template);
+ }
+ }
+
+ if ($_template->getSmarty()->debugging) {
+ $_template->getSmarty()->getDebug()->start_cache($_template);
+ }
+
+ $this->getRenderedTemplateCode($_template, $this->unifunc);
+
+ if ($_template->getSmarty()->debugging) {
+ $_template->getSmarty()->getDebug()->end_cache($_template);
+ }
+
+ }
+
+ /**
+ * Check if cache is valid, lock cache if required
+ *
+ * @param Template $_template
+ *
+ * @return bool flag true if cache is valid
+ * @throws Exception
+ */
+ public function isCached(Template $_template) {
+ if ($this->valid !== null) {
+ return $this->valid;
+ }
+ while (true) {
+ while (true) {
+ if ($this->exists === false || $_template->getSmarty()->force_compile || $_template->getSmarty()->force_cache) {
+ $this->valid = false;
+ } else {
+ $this->valid = true;
+ }
+ if ($this->valid && $_template->caching === \Smarty\Smarty::CACHING_LIFETIME_CURRENT
+ && $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime)
+ ) {
+ // lifetime expired
+ $this->valid = false;
+ }
+ if ($this->valid && $_template->compile_check === \Smarty\Smarty::COMPILECHECK_ON
+ && $_template->getSource()->getTimeStamp() > $this->timestamp
+ ) {
+ $this->valid = false;
+ }
+ if ($this->valid || !$_template->getSmarty()->cache_locking) {
+ break;
+ }
+ if (!$this->handler->locked($_template->getSmarty(), $this)) {
+ $this->handler->acquireLock($_template->getSmarty(), $this);
+ break 2;
+ }
+ $this->handler->populate($this, $_template);
+ }
+ if ($this->valid) {
+ if (!$_template->getSmarty()->cache_locking || $this->handler->locked($_template->getSmarty(), $this) === null) {
+ // load cache file for the following checks
+ if ($_template->getSmarty()->debugging) {
+ $_template->getSmarty()->getDebug()->start_cache($_template);
+ }
+ if ($this->handler->process($_template, $this) === false) {
+ $this->valid = false;
+ } else {
+ $this->processed = true;
+ }
+ if ($_template->getSmarty()->debugging) {
+ $_template->getSmarty()->getDebug()->end_cache($_template);
+ }
+ } else {
+ $this->is_locked = true;
+ continue;
+ }
+ } else {
+ return $this->valid;
+ }
+ if ($this->valid && $_template->caching === \Smarty\Smarty::CACHING_LIFETIME_SAVED
+ && $_template->getCached()->cache_lifetime >= 0
+ && (time() > ($_template->getCached()->timestamp + $_template->getCached()->cache_lifetime))
+ ) {
+ $this->valid = false;
+ }
+ if ($_template->getSmarty()->cache_locking) {
+ if (!$this->valid) {
+ $this->handler->acquireLock($_template->getSmarty(), $this);
+ } elseif ($this->is_locked) {
+ $this->handler->releaseLock($_template->getSmarty(), $this);
+ }
+ }
+ return $this->valid;
+ }
+ return $this->valid;
+ }
+
+ /**
+ * Process cached template
+ *
+ * @param Template $_template template object
+ */
+ private function process(Template $_template) {
+ if ($this->handler->process($_template, $this) === false) {
+ $this->valid = false;
+ }
+ $this->processed = $this->valid;
+ }
+
+ /**
+ * Read cache content from handler
+ *
+ * @param Template $_template template object
+ *
+ * @return string|false content
+ */
+ public function readCache(Template $_template) {
+ if (!$_template->getSource()->handler->recompiled) {
+ return $this->handler->retrieveCachedContent($_template);
+ }
+ return false;
+ }
+
+ /**
+ * Write this cache object to handler
+ *
+ * @param string $content content to cache
+ *
+ * @return bool success
+ */
+ public function writeCache(Template $_template, $content) {
+ if (!$_template->getSource()->handler->recompiled) {
+ if ($this->handler->storeCachedContent($_template, $content)) {
+ $this->content = null;
+ $this->timestamp = time();
+ $this->exists = true;
+ $this->valid = true;
+ $this->cache_lifetime = $_template->cache_lifetime;
+ $this->processed = false;
+ if ($_template->getSmarty()->cache_locking) {
+ $this->handler->releaseLock($_template->getSmarty(), $this);
+ }
+ return true;
+ }
+ $this->content = null;
+ $this->timestamp = false;
+ $this->exists = false;
+ $this->valid = false;
+ $this->processed = false;
+ }
+ return false;
+ }
+
+ /**
+ * Cache was invalid , so render from compiled and write to cache
+ *
+ * @param Template $_template
+ * @param bool $no_output_filter
+ *
+ * @throws \Smarty\Exception
+ */
+ private function updateCache(Template $_template, $no_output_filter) {
+
+ ob_start();
+
+ $_template->getCompiled()->render($_template);
+
+ if ($_template->getSmarty()->debugging) {
+ $_template->getSmarty()->getDebug()->start_cache($_template);
+ }
+
+ $this->removeNoCacheHash($_template, $no_output_filter);
+ $this->process($_template);
+
+ if ($_template->getSmarty()->debugging) {
+ $_template->getSmarty()->getDebug()->end_cache($_template);
+ }
+ }
+
+ /**
+ * Sanitize content and write it to cache resource
+ *
+ * @param Template $_template
+ * @param bool $no_output_filter
+ *
+ * @throws \Smarty\Exception
+ */
+ private function removeNoCacheHash(Template $_template, $no_output_filter) {
+ $php_pattern = '/(<%|%>|<\?php|<\?|\?>|
diff --git a/src/includes/smarty-5.4.1/src/functions.php b/src/includes/smarty-5.4.1/src/functions.php
new file mode 100644
index 0000000..590789b
--- /dev/null
+++ b/src/includes/smarty-5.4.1/src/functions.php
@@ -0,0 +1,253 @@
+
+ *
+ * @param DateTime|int|string $string date object, timestamp or string that can be converted using strtotime()
+ *
+ * @return int
+ */
+function smarty_make_timestamp($string)
+{
+ if (empty($string)) {
+ // use "now":
+ return time();
+ } elseif ($string instanceof DateTime
+ || (interface_exists('DateTimeInterface', false) && $string instanceof DateTimeInterface)
+ ) {
+ return (int)$string->format('U'); // PHP 5.2 BC
+ } elseif (strlen($string) === 14 && ctype_digit((string)$string)) {
+ // it is mysql timestamp format of YYYYMMDDHHMMSS?
+ return mktime(
+ substr($string, 8, 2),
+ substr($string, 10, 2),
+ substr($string, 12, 2),
+ substr($string, 4, 2),
+ substr($string, 6, 2),
+ substr($string, 0, 4)
+ );
+ } elseif (is_numeric($string)) {
+ // it is a numeric string, we handle it as timestamp
+ return (int)$string;
+ } else {
+ // strtotime should handle it
+ $time = strtotime($string);
+ if ($time === -1 || $time === false) {
+ // strtotime() was not able to parse $string, use "now":
+ return time();
+ }
+ return $time;
+ }
+}
+
+/**
+ * Multibyte string replace
+ *
+ * @param string|string[] $search the string to be searched
+ * @param string|string[] $replace the replacement string
+ * @param string $subject the source string
+ * @param int &$count number of matches found
+ *
+ * @return string replaced string
+ * @author Rodney Rehm
+ */
+function smarty_mb_str_replace($search, $replace, $subject, &$count = 0)
+{
+ if (!is_array($search) && is_array($replace)) {
+ return false;
+ }
+ if (is_array($subject)) {
+ // call mb_replace for each single string in $subject
+ foreach ($subject as &$string) {
+ $string = smarty_mb_str_replace($search, $replace, $string, $c);
+ $count += $c;
+ }
+ } elseif (is_array($search)) {
+ if (!is_array($replace)) {
+ foreach ($search as &$string) {
+ $subject = smarty_mb_str_replace($string, $replace, $subject, $c);
+ $count += $c;
+ }
+ } else {
+ $n = max(count($search), count($replace));
+ while ($n--) {
+ $subject = smarty_mb_str_replace(current($search), current($replace), $subject, $c);
+ $count += $c;
+ next($search);
+ next($replace);
+ }
+ }
+ } else {
+ $mb_reg_charset = mb_regex_encoding();
+ // Check if mbstring regex is using UTF-8
+ $reg_is_unicode = !strcasecmp($mb_reg_charset, "UTF-8");
+ if(!$reg_is_unicode) {
+ // ...and set to UTF-8 if not
+ mb_regex_encoding("UTF-8");
+ }
+
+ // See if charset used by Smarty is matching one used by regex...
+ $current_charset = mb_regex_encoding();
+ $convert_result = (bool)strcasecmp(\Smarty\Smarty::$_CHARSET, $current_charset);
+ if($convert_result) {
+ // ...convert to it if not.
+ $subject = mb_convert_encoding($subject, $current_charset, \Smarty\Smarty::$_CHARSET);
+ $search = mb_convert_encoding($search, $current_charset, \Smarty\Smarty::$_CHARSET);
+ $replace = mb_convert_encoding($replace, $current_charset, \Smarty\Smarty::$_CHARSET);
+ }
+
+ $parts = mb_split(preg_quote($search), $subject ?? "") ?: array();
+ // If original regex encoding was not unicode...
+ if(!$reg_is_unicode) {
+ // ...restore original regex encoding to avoid breaking the system.
+ mb_regex_encoding($mb_reg_charset);
+ }
+ if($parts === false) {
+ // This exception is thrown if call to mb_split failed.
+ // Usually it happens, when $search or $replace are not valid for given mb_regex_encoding().
+ // There may be other cases for it to fail, please file an issue if you find a reproducible one.
+ throw new Exception("Source string is not a valid $current_charset sequence (probably)");
+ }
+
+ $count = count($parts) - 1;
+ $subject = implode($replace, $parts);
+ // Convert results back to charset used by Smarty, if needed.
+ if($convert_result) {
+ $subject = mb_convert_encoding($subject, \Smarty\Smarty::$_CHARSET, $current_charset);
+ }
+ }
+ return $subject;
+}
+/**
+ * escape_special_chars common function
+ * Function: smarty_function_escape_special_chars
+ * Purpose: used by other smarty functions to escape
+ * special chars except for already escaped ones
+ *
+ * @author Monte Ohrt
+ *
+ * @param string $string text that should by escaped
+ *
+ * @return string
+ */
+function smarty_function_escape_special_chars($string)
+{
+ if (!is_array($string)) {
+ $string = htmlspecialchars((string) $string, ENT_COMPAT, \Smarty\Smarty::$_CHARSET, false);
+ }
+ return $string;
+}
+
+/**
+ * Smarty wordwrap supporting multibyte
+ * Name: smarty_mb_wordwrap
+ * Purpose: Wrap a string to a given number of characters
+ *
+ * @link https://php.net/manual/en/function.wordwrap.php for similarity
+ *
+ * @param string $str the string to wrap
+ * @param int $width the width of the output
+ * @param string $break the character used to break the line
+ * @param boolean $cut ignored parameter, just for the sake of
+ *
+ * @return string wrapped string
+ * @author Rodney Rehm
+ */
+function smarty_mb_wordwrap($str, $width = 75, $break = "\n", $cut = false)
+{
+ // break words into tokens using white space as a delimiter
+ $tokens = preg_split('!(\s)!S' . \Smarty\Smarty::$_UTF8_MODIFIER, $str, -1, PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE);
+ $length = 0;
+ $t = '';
+ $_previous = false;
+ $_space = false;
+ foreach ($tokens as $_token) {
+ $token_length = mb_strlen($_token, \Smarty\Smarty::$_CHARSET);
+ $_tokens = array($_token);
+ if ($token_length > $width) {
+ if ($cut) {
+ $_tokens = preg_split(
+ '!(.{' . $width . '})!S' . \Smarty\Smarty::$_UTF8_MODIFIER,
+ $_token,
+ -1,
+ PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE
+ );
+ }
+ }
+ foreach ($_tokens as $token) {
+ $_space = !!preg_match('!^\s$!S' . \Smarty\Smarty::$_UTF8_MODIFIER, $token);
+ $token_length = mb_strlen($token, \Smarty\Smarty::$_CHARSET);
+ $length += $token_length;
+ if ($length > $width) {
+ // remove space before inserted break
+ if ($_previous) {
+ $t = mb_substr($t, 0, -1, \Smarty\Smarty::$_CHARSET);
+ }
+ if (!$_space) {
+ // add the break before the token
+ if (!empty($t)) {
+ $t .= $break;
+ }
+ $length = $token_length;
+ }
+ } elseif ($token === "\n") {
+ // hard break must reset counters
+ $length = 0;
+ }
+ $_previous = $_space;
+ // add the token
+ $t .= $token;
+ }
+ }
+ return $t;
+}
diff --git a/src/index.php b/src/index.php
index 8ad4ab6..5f7e526 100644
--- a/src/index.php
+++ b/src/index.php
@@ -28,13 +28,17 @@ else {
}
if (!empty($_GET["message"])) {
- $message = $_GET["message"];
+ $message = filter_var(trim($_GET["message"], FILTER_SANITIZE_STRING));;
+ $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
}
/* if we've got `page' on the query string, set the session page indicator. */
if (isset($_GET["offset"])) {
- $_SESSION["offset"] = $_GET["offset"];
- $offset = $_GET["offset"];
+ $offset = filter_var(trim($_GET["offset"]), FILTER_SANITIZE_NUMBER_INT);
+ if (filter_var($offset, FILTER_SANITIZE_NUMBER_INT) === false || $offset == "" || !is_numeric($offset) || $offset < 0) {
+ die("Invalid page offset ({$_GET["offset"]})");
+ }
+ $_SESSION["offset"] = $offset;
}
else if (isset($_SESSION["offset"])) {
$offset = $_SESSION["offset"];
@@ -43,49 +47,81 @@ else {
$offset = 0;
}
+if (isset($_GET["messageid"])) {
+ $messageid = filter_var(trim($_GET["messageid"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($messageid, FILTER_SANITIZE_NUMBER_INT) === false || $messageid == "" || !is_numeric($messageid) || $messageid < 0) {
+ die("Invalid messageid ({$_GET["messageid"]})");
+ }
+}
+
+if (isset($_GET["shopper"])) {
+ $shopper = filter_var(trim($_GET["shopper"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($shopper, FILTER_SANITIZE_NUMBER_INT) === false || $shopper == "" || !is_numeric($shopper) || $shopper < 0) {
+ die("Invalid shopper ({$_GET["shopper"]})");
+ }
+}
+
+if (isset($_GET["shopfor"])) {
+ $shopfor = filter_var(trim($_GET["shopfor"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($shopfor, FILTER_SANITIZE_NUMBER_INT) === false || $shopfor == "" || !is_numeric($shopfor) || $shopfor < 0) {
+ die("Invalid shopfor ({$_GET["shopfor"]})");
+ }
+}
+
+if (isset($_GET["shoppee"])) {
+ $shoppee = filter_var(trim($_GET["shoppee"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($shoppee, FILTER_SANITIZE_NUMBER_INT) === false || $shoppee == "" || !is_numeric($shoppee) || $shoppee < 0) {
+ die("Invalid shoppee ({$_GET["shoppee"]})");
+ }
+}
+
if (!empty($_GET["action"])) {
$action = $_GET["action"];
if ($action == "ack") {
$stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}messages SET isread = 1 WHERE messageid = ?");
- $stmt->bindValue(1, (int) $_GET["messageid"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $messageid, PDO::PARAM_INT);
$stmt->execute();
}
else if ($action == "approve") {
$stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}shoppers SET pending = 0 WHERE shopper = ? AND mayshopfor = ?");
- $stmt->bindValue(1, (int) $_GET["shopper"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $shopper, PDO::PARAM_INT);
$stmt->bindParam(2, $userid, PDO::PARAM_INT);
$stmt->execute();
- sendMessage($userid,(int) $_GET["shopper"],$_SESSION["fullname"] . " has approved your request to shop for him/her.", $smarty->dbh(), $smarty->opt());
+ sendMessage($userid,(int) $shopper,$_SESSION["fullname"] . " has approved your request to shop for him/her.", $smarty->dbh(), $smarty->opt());
}
else if ($action == "decline") {
- $stmt = $smarty->dbh()->prepare("DELETE FROM {$opt["table_prefix"]}shoppers WHERE shopper = ? AND mayshopfor = ?");
- $stmt->bindValue(1, (int) $_GET["shopper"], PDO::PARAM_INT);
+ $stmt = $smarty->dbh()->prepare("DELETE FROM {$opt["table_prefix"]}shoppers WHERE shopper = ? AND mayshopfor = ?");
+ $stmt->bindValue(1, (int) $shopper, PDO::PARAM_INT);
$stmt->bindParam(2, $userid, PDO::PARAM_INT);
$stmt->execute();
- sendMessage($userid,(int) $_GET["shopper"],$_SESSION["fullname"] . " has declined your request to shop for him/her.", $smarty->dbh(), $smarty->opt());
+ sendMessage($userid,(int) $shopper,$_SESSION["fullname"] . " has declined your request to shop for him/her.", $smarty->dbh(), $smarty->opt());
}
else if ($action == "request") {
$stmt = $smarty->dbh()->prepare("INSERT INTO {$opt["table_prefix"]}shoppers(shopper,mayshopfor,pending) VALUES(?, ?, ?)");
$stmt->bindParam(1, $userid, PDO::PARAM_INT);
- $stmt->bindValue(2, (int) $_GET["shopfor"], PDO::PARAM_INT);
+ $stmt->bindValue(2, (int) $shopfor, PDO::PARAM_INT);
$stmt->bindValue(3, $opt["shop_requires_approval"], PDO::PARAM_BOOL);
$stmt->execute();
if ($opt["shop_requires_approval"]) {
- sendMessage($userid,(int) $_GET["shopfor"],$_SESSION["fullname"] . " has requested to shop for you. Please approve or decline this request.", $smarty->dbh(), $smarty->opt());
+ sendMessage($userid,(int) $shopfor,$_SESSION["fullname"] . " has requested to shop for you. Please approve or decline this request.", $smarty->dbh(), $smarty->opt());
}
}
else if ($action == "cancel") {
// this works for either cancelling a request or "unshopping" for a user.
$stmt = $smarty->dbh()->prepare("DELETE FROM {$opt["table_prefix"]}shoppers WHERE shopper = ? AND mayshopfor = ?");
$stmt->bindParam(1, $userid, PDO::PARAM_INT);
- $stmt->bindValue(2, (int) $_GET["shopfor"], PDO::PARAM_INT);
+ $stmt->bindValue(2, (int) $shopfor, PDO::PARAM_INT);
$stmt->execute();
}
else if ($action == "subscribe") {
// ensure the current user can shop for that user first.
$stmt = $smarty->dbh()->prepare("SELECT pending FROM {$opt["table_prefix"]}shoppers WHERE shopper = ? AND mayshopfor = ?");
$stmt->bindParam(1, $userid, PDO::PARAM_INT);
- $stmt->bindValue(2, (int) $_GET["shoppee"], PDO::PARAM_INT);
+ $stmt->bindValue(2, (int) $shoppee, PDO::PARAM_INT);
$stmt->execute();
if ($row = $stmt->fetch()) {
if ($row["pending"]) {
@@ -97,44 +133,61 @@ if (!empty($_GET["action"])) {
}
$stmt = $smarty->dbh()->prepare("INSERT INTO {$opt["table_prefix"]}subscriptions(publisher, subscriber) VALUES(?, ?)");
- $stmt->bindValue(1, (int) $_GET["shoppee"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $shoppee, PDO::PARAM_INT);
$stmt->bindParam(2, $userid, PDO::PARAM_INT);
$stmt->execute();
}
else if ($action == "unsubscribe") {
$stmt = $smarty->dbh()->prepare("DELETE FROM {$opt["table_prefix"]}subscriptions WHERE publisher = ? AND subscriber = ?");
- $stmt->bindValue(1, (int) $_GET["shoppee"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $shoppee, PDO::PARAM_INT);
$stmt->bindParam(2, $userid, PDO::PARAM_INT);
$stmt->execute();
}
}
-if (!empty($_GET["mysort"]))
- $_SESSION["mysort"] = $_GET["mysort"];
-
+$reset_sortdir = false;
+if (!empty($_GET["mysort"])) {
+ $mysort = filter_var(trim($_GET["mysort"]), FILTER_SANITIZE_STRING);
+ $mysort = htmlspecialchars($mysort, ENT_QUOTES, 'UTF-8');
+ if (isset($_SESSION["mysort"]) && $_SESSION["mysort"] != $mysort) {
+ $reset_sortdir = true;
+ }
+ $_SESSION["mysort"] = $mysort;
+}
+
+if (!empty($_GET["sortdir"]) && !$reset_sortdir) {
+ $sortdir = strtoupper(trim($_GET["sortdir"])) == "DESC" ? "DESC" : "ASC";
+ $_SESSION["sortdir"] = $sortdir;
+}
+
+if (!isset($_SESSION["sortdir"]) || $reset_sortdir) {
+ $sortdir = "ASC";
+ $_SESSION["sortdir"] = $sortdir;
+}
+
if (!isset($_SESSION["mysort"])) {
- $sortby = "rankorder DESC, i.name";
+ $sortby = "rankorder {$_SESSION['sortdir']}, i.name";
$_SESSION["mysort"] = "ranking";
}
else {
switch ($_SESSION["mysort"]) {
- case "ranking":
- $sortby = "rankorder DESC, i.name";
- break;
case "name":
- $sortby = "i.name";
+ $sortby = "i.name {$_SESSION['sortdir']}";
+ break;
+ case "source":
+ $sortby = "source {$_SESSION['sortdir']}, rankorder, i.name";
break;
case "price":
- $sortby = "price, rankorder DESC, i.name";
+ $sortby = "price {$_SESSION['sortdir']}, rankorder, i.name";
break;
case "category":
- $sortby = "c.category, rankorder DESC, i.name";
+ $sortby = "c.category {$_SESSION['sortdir']}, rankorder, i.name";
break;
default:
- $sortby = "rankorder DESC, i.name";
+ $sortby = "rankorder {$_SESSION['sortdir']}, i.name";
}
}
-$stmt = $smarty->dbh()->prepare("SELECT itemid, name, description, c.category, price, url, rendered, comment, image_filename FROM {$opt["table_prefix"]}items i LEFT OUTER JOIN {$opt["table_prefix"]}categories c ON c.categoryid = i.category LEFT OUTER JOIN {$opt["table_prefix"]}ranks r ON r.ranking = i.ranking WHERE userid = ? ORDER BY " . $sortby);
+$stmt = $smarty->dbh()->prepare("SELECT itemid, name, description, i.category as catid, c.category, price, price as pricenum, source, url, i.ranking as rankid, rendered, comment, quantity, image_filename FROM {$opt["table_prefix"]}items i LEFT OUTER JOIN {$opt["table_prefix"]}categories c ON c.categoryid = i.category LEFT OUTER JOIN {$opt["table_prefix"]}ranks r ON r.ranking = i.ranking WHERE userid = ? ORDER BY " . $sortby);
$stmt->bindParam(1, $userid, PDO::PARAM_INT);
$stmt->execute();
$myitems_count = 0;
@@ -145,6 +198,7 @@ for ($i = 0; $i < $offset; $i++, ++$myitems_count) {
$i = 0;
while ($i++ < $opt["items_per_page"] && $row = $stmt->fetch()) {
$row['price'] = formatPrice($row['price'], $opt);
+ $row['urlhost'] = preg_replace("/^(https?:\/\/)?(www\.)?([^\/]+)(\/.*)?$/", "$3", $row['url']);
$myitems[] = $row;
++$myitems_count;
}
@@ -152,6 +206,20 @@ while ($stmt->fetch()) {
++$myitems_count;
}
+$stmt = $smarty->dbh()->prepare("SELECT categoryid, category FROM {$opt["table_prefix"]}categories ORDER BY category");
+$stmt->execute();
+$categories = array();
+while ($row = $stmt->fetch()) {
+ $categories[] = $row;
+}
+
+$stmt = $smarty->dbh()->prepare("SELECT ranking, title FROM {$opt["table_prefix"]}ranks ORDER BY rankorder");
+$stmt->execute();
+$ranks = array();
+while ($row = $stmt->fetch()) {
+ $ranks[] = $row;
+}
+
$stmt = $smarty->dbh()->prepare("SELECT u.userid, u.fullname, u.comment, u.list_stamp, ISNULL(sub.subscriber) AS is_unsubscribed, COUNT(i.itemid) AS itemcount " .
"FROM {$opt["table_prefix"]}shoppers s " .
"INNER JOIN {$opt["table_prefix"]}users u ON u.userid = s.mayshopfor " .
@@ -196,7 +264,7 @@ $prospects = array();
while ($row = $stmt->fetch()) {
$prospects[] = $row;
}
-
+
$stmt = $smarty->dbh()->prepare("SELECT messageid, u.fullname, message, created " .
"FROM {$opt["table_prefix"]}messages m " .
"INNER JOIN {$opt["table_prefix"]}users u ON u.userid = m.sender " .
@@ -258,14 +326,14 @@ while ($row = $stmt->fetch()) {
$events[] = $thisevent;
}
}
-
+
function compareEvents($a, $b) {
if ($a["daysleft"] == $b["daysleft"])
return 0;
else
return ($a["daysleft"] > $b["daysleft"]) ? 1 : -1;
}
-
+
// i couldn't figure out another way to do this, so here goes.
// sort() wanted to sort based on the array keys, which were 0..n - 1, so that was useless.
usort($events, "compareEvents");
@@ -290,7 +358,7 @@ if (($_SESSION["admin"] == 1) && $opt["newuser_requires_approval"]) {
$query = "SELECT userid, fullname, email, approved, initialfamilyid, familyname " .
"FROM {$opt["table_prefix"]}users u " .
"LEFT OUTER JOIN {$opt["table_prefix"]}families f ON f.familyid = u.initialfamilyid " .
- "WHERE approved = 0 " .
+ "WHERE approved = 0 " .
"ORDER BY fullname";
$stmt = $smarty->dbh()->prepare($query);
$stmt->execute();
@@ -304,6 +372,10 @@ $smarty->assign('fullname', $_SESSION['fullname']);
if (isset($message)) {
$smarty->assign('message', $message);
}
+$smarty->assign('mysort', $_SESSION['mysort']);
+$smarty->assign('sortdir', $_SESSION['sortdir']);
+$smarty->assign('categories', $categories);
+$smarty->assign('ranks', $ranks);
$smarty->assign('myitems', $myitems);
$smarty->assign('myitems_count', $myitems_count);
$smarty->assign('offset', $offset);
diff --git a/src/item.php b/src/item.php
index 6ec942b..524373c 100644
--- a/src/item.php
+++ b/src/item.php
@@ -20,7 +20,7 @@ $opt = $smarty->opt();
session_start();
if (!isset($_SESSION["userid"])) {
- header("Location: " . getFullPath("login.php"));
+ header("Location: " . getFullPath("login.php") . "?from=item.php");
exit;
}
else {
@@ -37,7 +37,11 @@ $category = 1;
$ranking = 3;
$comment = "";
$quantity = 1;
+$image_url = "";
$image_filename = "";
+$image_base_filename = "";
+$haserror = false;
+$error_message = "";
// for security, let's make sure that if an itemid was passed in, it belongs
// to $userid. all operations on this page should only be performed by
@@ -60,7 +64,7 @@ if (isset($_REQUEST["itemid"]) && $_REQUEST["itemid"] != "") {
$action = "";
if (!empty($_REQUEST["action"])) {
$action = $_REQUEST["action"];
-
+
if ($action == "insert" || $action == "update") {
/* validate the data. */
$name = trim($_REQUEST["name"]);
@@ -68,24 +72,28 @@ if (!empty($_REQUEST["action"])) {
$image_url = isset($_REQUEST["image_url"]) ? trim($_REQUEST["image_url"]) : "";
$description = isset($_REQUEST["description"]) ? trim($_REQUEST["description"]) : "";
$price = isset($_REQUEST["price"]) ? str_replace(",","",trim($_REQUEST["price"])) : "0";
+ $price = preg_replace("/^\$/", "", $price);
$source = isset($_REQUEST["source"]) ? trim($_REQUEST["source"]) : "";
$url = isset($_REQUEST["url"]) ? trim($_REQUEST["url"]) : "";
$category = isset($_REQUEST["category"]) ? trim($_REQUEST["category"]) : "1";
$ranking = isset($_REQUEST["ranking"]) ? $_REQUEST["ranking"] : "3";
$comment = isset($_REQUEST["comment"]) ? $_REQUEST["comment"] : "";
+ if (isset($_REQUEST["pricesymbol"]) && $_REQUEST["pricesymbol"] != $opt["currency_symbol"]) {
+ $price = "";
+ $comment = trim("$comment Price not in {$opt['currency_symbol']}, it is {$_REQUEST["pricesymbol"]}{$_REQUEST['price']}.");
+ }
$quantity = isset($_REQUEST["quantity"]) ? (int) $_REQUEST["quantity"] : 1;
- $haserror = false;
if ($name == "") {
$haserror = true;
- $name_error = "A name is required.";
+ $error_message = trim("$error_message A name is required.");
+ $name_error = true;
}
if ($image_url != "" && preg_match("/^http(s)?:\/\/([^\/]+)/i",$image_url)) {
$image_file_data = file_get_contents($image_url);
if ($image_file_data !== false) {
$temp_image = tempnam("/tmp","");
file_put_contents($temp_image, $image_file_data);
- error_log("MWE: temp_image: $temp_image");
$fh = fopen($temp_image, 'rb');
if ($fh) {
$header = fread($fh, 8);
@@ -105,7 +113,6 @@ if (!empty($_REQUEST["action"])) {
$ext = 'webp';
}
}
- error_log("MWE: ext: $ext");
if ($ext != "") {
$parts = pathinfo($_SERVER["SCRIPT_FILENAME"]);
$upload_dir = $parts['dirname'];
@@ -115,39 +122,45 @@ if (!empty($_REQUEST["action"])) {
unlink($temp_name);
// here's the name we really want to use. full path is included.
$image_filename = $temp_name . "." . $ext;
- error_log("MWE: image_filename: $image_filename");
// move the PHP temporary file to that filename.
rename($temp_image, $image_filename);
// fix permissions on the new file
chmod($image_filename, 0644);
// the name we're going to record in the DB is the filename without the path.
$image_base_filename = basename($image_filename);
- error_log("MWE: image_base_filename: $image_base_filename");
}
}
}
if ($bookmarklet == "1") {
- if ($source == "" && preg_match("/^Amazon.com:/", $name)) {
+ if ($source == "" && preg_match("/^Amazon.com:? *\| */", $name)) {
$source = "Amazon";
}
if ($source == "" && $url != "") {
$source = preg_replace("/^(https?:\/\/)?([^\/]+)(\/.*)?$/", "$2", $url);
+ $source = preg_replace("/^www\./", "", $source);
+ if (preg_match("/([a-zA-Z0-9_-]+)\.(com|net|org|biz|co\.uk)$/", $source)) {
+ $source = preg_replace("/([a-zA-Z0-9_-]+)\.(com|net|org|biz|co\.uk)$/", "$1", $source);
+ $source = ucfirst($source);
+ }
}
- $name = preg_replace("/^Amazon.com: /", "", $name);
+ $name = preg_replace("/^Amazon.com:? *\|? */", "", $name);
$name = preg_replace("/ : [A-Za-z0-9 &_,-]+/", "", $name);
}
- if (strlen($name) > 100 && $description == "") {
+ if (strlen($name) > 60 && $description == "") {
$description = $name;
}
- if (strlen($name) > 100) {
+ if (strlen($name) > 50) {
+ $name = preg_replace("/ at Amazon.*$/", "", $name);
+ $name = preg_replace("/^(.{30,100}?)([,.!?;:]).*$/", "$1", $name);
$name = substr($name, 0, 100);
}
if ($price == "" || !preg_match("/^\d*(\.\d{2})?$/i",$price)) {
$price = 0;
}
- if ($url != "" && !preg_match("/^http(s)?:\/\/([^\/]+)/i",$url)) {
+ if ($url != "" && !filter_var($url, FILTER_VALIDATE_URL)) {
$haserror = true;
- $url_error = "A well-formed URL is required in the format http://www.somesite.net/somedir/somefile.html .";
+ $error_message = trim("$error_message A well-formed URL is required in the format http://www.somesite.net/somedir/somefile.html.");
+ $url_error = true;
}
if ($category == "") {
$category = 1;
@@ -160,7 +173,7 @@ if (!empty($_REQUEST["action"])) {
}
}
- if (!isset($image_url) && isset($haserror) && !$haserror && isset($_REQUEST["image"])) {
+ if ($image_url == "" && $haserror !== true && isset($_REQUEST["image"])) {
if ($_REQUEST["image"] == "remove" || $_REQUEST["image"] == "replace") {
deleteImageForItem((int) $_REQUEST["itemid"], $smarty->dbh(), $smarty->opt());
}
@@ -186,7 +199,7 @@ if (!empty($_REQUEST["action"])) {
$image_base_filename = basename($image_filename);
}
}
-
+
if ($action == "delete") {
try {
/* find out if this item is bought or reserved. */
@@ -208,7 +221,7 @@ if (!empty($_REQUEST["action"])) {
$smarty->opt());
}
}
-
+
deleteImageForItem((int) $_REQUEST["itemid"], $smarty->dbh(), $smarty->opt());
$stmt = $smarty->dbh()->prepare("DELETE FROM {$opt["table_prefix"]}items WHERE itemid = ?");
@@ -216,7 +229,7 @@ if (!empty($_REQUEST["action"])) {
$stmt->execute();
// TODO: are we leaking allocs records here?
-
+
stampUser($userid, $smarty->dbh(), $smarty->opt());
processSubscriptions($userid, $action, $name, $smarty->dbh(), $smarty->opt());
@@ -260,7 +273,7 @@ if (!empty($_REQUEST["action"])) {
else if ($action == "insert") {
if (!$haserror) {
$stmt = $smarty->dbh()->prepare("INSERT INTO {$opt["table_prefix"]}items(userid,name,description,price,source,category,url,ranking,comment,quantity,image_filename) " .
- "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->bindParam(1, $userid, PDO::PARAM_INT);
$stmt->bindParam(2, $name, PDO::PARAM_STR);
$stmt->bindParam(3, $description, PDO::PARAM_STR);
@@ -271,12 +284,12 @@ if (!empty($_REQUEST["action"])) {
$stmt->bindParam(8, $ranking, PDO::PARAM_INT);
$stmt->bindParam(9, $comment, PDO::PARAM_STR);
$stmt->bindParam(10, $quantity, PDO::PARAM_INT);
- if (!isset($image_base_filename) || $image_base_filename == "") {
- $image_base_filename = NULL;
- }
+ if (!isset($image_base_filename) || $image_base_filename == "") {
+ $image_base_filename = NULL;
+ }
$stmt->bindParam(11, $image_base_filename, PDO::PARAM_STR);
$stmt->execute();
-
+
stampUser($userid, $smarty->dbh(), $smarty->opt());
processSubscriptions($userid, $action, $name, $smarty->dbh(), $smarty->opt());
@@ -295,20 +308,20 @@ if (!empty($_REQUEST["action"])) {
"category = ?, " .
"url = ?, " .
"ranking = ?, " .
- "comment = ?, " .
+ "comment = ?, " .
"quantity = ? " .
($image_base_filename != "" ? ", image_filename = ? " : "") .
"WHERE itemid = ?");
$stmt->bindParam(1, $name, PDO::PARAM_STR);
$stmt->bindParam(2, $description, PDO::PARAM_STR);
$stmt->bindParam(3, $price);
- $stmt->bindParam(4, $source, PDO::PARAM_STR);
- $stmt->bindParam(5, $category, PDO::PARAM_INT);
- $stmt->bindParam(6, $url, PDO::PARAM_STR);
- $stmt->bindParam(7, $ranking, PDO::PARAM_INT);
- $stmt->bindParam(8, $comment, PDO::PARAM_STR);
- $stmt->bindParam(9, $quantity, PDO::PARAM_INT);
- if ($image_base_filename != "") {
+ $stmt->bindParam(4, $source, PDO::PARAM_STR);
+ $stmt->bindParam(5, $category, PDO::PARAM_INT);
+ $stmt->bindParam(6, $url, PDO::PARAM_STR);
+ $stmt->bindParam(7, $ranking, PDO::PARAM_INT);
+ $stmt->bindParam(8, $comment, PDO::PARAM_STR);
+ $stmt->bindParam(9, $quantity, PDO::PARAM_INT);
+ if ($image_base_filename != "") {
$stmt->bindParam(10, $image_base_filename, PDO::PARAM_STR);
$stmt->bindValue(11, (int) $_REQUEST["itemid"], PDO::PARAM_INT);
}
@@ -321,7 +334,7 @@ if (!empty($_REQUEST["action"])) {
processSubscriptions($userid, $action, $name, $smarty->dbh(), $smarty->opt());
header("Location: " . getFullPath("index.php"));
- exit;
+ exit;
}
}
else {
@@ -337,7 +350,7 @@ while ($row = $stmt->fetch()) {
$categories[] = $row;
}
-$stmt = $smarty->dbh()->prepare("SELECT ranking, title FROM {$opt["table_prefix"]}ranks ORDER BY rankorder DESC");
+$stmt = $smarty->dbh()->prepare("SELECT ranking, title FROM {$opt["table_prefix"]}ranks ORDER BY rankorder");
$stmt->execute();
$ranks = array();
while ($row = $stmt->fetch()) {
@@ -347,6 +360,9 @@ while ($row = $stmt->fetch()) {
$smarty->assign('userid', $userid);
$smarty->assign('action', $action);
$smarty->assign('haserror', isset($haserror) ? $haserror : false);
+if ($error_message != "") {
+ $smarty->assign('error_message', $error_message);
+}
if (isset($_REQUEST['itemid'])) {
$smarty->assign('itemid', (int) $_REQUEST['itemid']);
}
@@ -386,5 +402,5 @@ $smarty->assign('image_filename', $image_filename);
$smarty->assign('comment', $comment);
$smarty->assign('categories', $categories);
$smarty->assign('ranks', $ranks);
-$smarty->display('item.tpl');
+header("Location: " . getFullPath("index.php"));
?>
diff --git a/src/js/bs-components.js b/src/js/bs-components.js
new file mode 100644
index 0000000..a905083
--- /dev/null
+++ b/src/js/bs-components.js
@@ -0,0 +1,15 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
+ const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
+ const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]')
+ const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
+});
+/*
+const myModal = document.getElementById('myModal')
+const myInput = document.getElementById('myInput')
+
+myModal.addEventListener('shown.bs.modal', () => {
+ myInput.focus()
+})
+
+*/
diff --git a/src/js/giftreg.js b/src/js/giftreg.js
index b8a2921..9472cbd 100644
--- a/src/js/giftreg.js
+++ b/src/js/giftreg.js
@@ -1,9 +1,9 @@
// based on http://alittlecode.com/files/jQuery-Validate-Demo/
function validate_highlight(label) {
- $(label).closest('.control-group').addClass('error');
+ $(label).closest('.row').addClass('danger');
}
function validate_success(label) {
- $(label).addClass('valid').closest('.control-group').removeClass('error');
+ $(label).addClass('valid').closest('.row').removeClass('danger');
}
diff --git a/src/js/themeswitcher.js b/src/js/themeswitcher.js
index 8a0dabf..d3c92a0 100644
--- a/src/js/themeswitcher.js
+++ b/src/js/themeswitcher.js
@@ -4,6 +4,8 @@
* Licensed under the Creative Commons Attribution 3.0 Unported License.
*/
+// Downloaded from https://getbootstrap.com/docs/5.3/assets/js/color-modes.js
+
(() => {
'use strict'
@@ -36,21 +38,34 @@
return
}
- const themeSwitcherText = document.querySelector('#bd-theme-text')
- const activeThemeIcon = document.querySelector('.theme-icon-active use')
- const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
- const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
-
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active')
element.setAttribute('aria-pressed', 'false')
})
- btnToActive.classList.add('active')
- btnToActive.setAttribute('aria-pressed', 'true')
- activeThemeIcon.setAttribute('href', svgOfActiveBtn)
- const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
- themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
+ // Changes by github.com/merdely: change theme images throughout page
+ document.querySelectorAll('.theme-image').forEach(function(image) {
+ image.src = image.getAttribute('data-' +
+ document.documentElement.getAttribute('data-bs-theme')
+ + '-src');
+ });
+
+ // Changes by github.com/merdely: use img instead of svg
+ document.querySelectorAll('.theme-image-active').forEach(function(image) {
+ image.src = image.getAttribute('data-' + theme + '-' +
+ document.documentElement.getAttribute('data-bs-theme')
+ + '-src');
+ });
+ document.querySelectorAll('.theme-image-check').forEach(function(image) {
+ // image.parentElement.classList.remove('active');
+ // image.parentElement.setAttribute('aria-pressed', 'false');
+ image.classList.add('d-none');
+ });
+ document.querySelectorAll(`#theme-${theme}`).forEach(function(image) {
+ // image.parentElement.classList.add('active');
+ // image.parentElement.setAttribute('aria-pressed', 'true');
+ image.classList.remove('d-none');
+ });
if (focus) {
themeSwitcher.focus()
@@ -60,7 +75,8 @@
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
const storedTheme = getStoredTheme()
if (storedTheme !== 'light' && storedTheme !== 'dark') {
- setTheme(getPreferredTheme())
+ setTheme(getPreferredTheme());
+ showActiveTheme(getPreferredTheme());
}
})
diff --git a/src/login.php b/src/login.php
index cca2ef5..b691c67 100644
--- a/src/login.php
+++ b/src/login.php
@@ -18,15 +18,25 @@ require_once(dirname(__FILE__) . "/includes/MySmarty.class.php");
$smarty = new MySmarty();
$opt = $smarty->opt();
+$pages = [ "admin.php", "categories.php", "event.php", "families.php", "forgot.php", "help.php", "index.php", "item.php", "login.php", "message.php", "mylist.php", "profile.php", "ranks.php", "receive.php", "shoplist.php", "shop.php", "signup.php", "users.php", ];
+
if (isset($_GET["action"])) {
if ($_GET["action"] == "logout") {
session_start();
session_destroy();
+ $smarty->assign('reset_theme', 'true');
}
}
+if (isset($_GET["from"])) {
+ $from = filter_var(trim($_GET["from"], FILTER_SANITIZE_STRING));;
+ $from = htmlspecialchars($from, ENT_QUOTES, 'UTF-8');
+} else
+ $from = "";
+
if (!empty($_POST["username"])) {
- $username = $_POST["username"];
+ $username = filter_var(strtolower(trim($_REQUEST["username"])), FILTER_SANITIZE_STRING);
+ $username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
$password = $_POST["password"];
try {
@@ -42,8 +52,11 @@ if (!empty($_POST["username"])) {
$_SESSION["admin"] = $row["admin"];
$_SESSION["show_helptext"] = $row["show_helptext"];
$opt['show_helptext'] = $row["show_helptext"];
-
- header("Location: " . getFullPath("index.php"));
+
+ if (in_array($from, $pages))
+ header("Location: " . getFullPath($from));
+ else
+ header("Location: " . getFullPath("index.php"));
exit;
}
}
@@ -51,10 +64,12 @@ if (!empty($_POST["username"])) {
die("sql exception: " . $e->getMessage());
}
+ $smarty->assign('from', $from);
$smarty->assign('username', $username);
$smarty->display('login.tpl');
}
else {
+ $smarty->assign('from', $from);
$smarty->display('login.tpl');
}
?>
diff --git a/src/message.php b/src/message.php
index 40a0866..2f58b1f 100644
--- a/src/message.php
+++ b/src/message.php
@@ -20,7 +20,7 @@ $opt = $smarty->opt();
session_start();
if (!isset($_SESSION["userid"])) {
- header("Location: " . getFullPath("login.php"));
+ header("Location: " . getFullPath("login.php") . "?from=message.php");
exit;
}
else {
@@ -28,14 +28,27 @@ else {
}
$action = empty($_GET["action"]) ? "" : $_GET["action"];
+$failedcount = 0;
+$recipcount = 0;
if ($action == "send") {
- $msg = $_GET["msg"];
+ $msg = filter_var(trim($_GET["msg"], FILTER_SANITIZE_STRING));;
+ $msg = htmlspecialchars($msg, ENT_QUOTES, 'UTF-8');
- for ($i = 0; $i < count($_GET["recipients"]); $i++)
- sendMessage($userid, (int) $_GET["recipients"][$i], $msg, $smarty->dbh(), $smarty->opt());
-
- header("Location: " . getFullPath("index.php?message=Your+message+has+been+sent+to+" . count($_GET["recipients"]) . "+recipient(s)."));
+ for ($i = 0; $i < count($_GET['recipients']); $i++) {
+ $recipient = filter_var(trim($_GET["recipients"][$i]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($recipient, FILTER_SANITIZE_NUMBER_INT) !== false && $recipient != "" && is_numeric($recipient) && $recipient > 0) {
+ sendMessage($userid, (int) $recipient, $msg, $smarty->dbh(), $smarty->opt());
+ $recipcount++;
+ } else
+ $failedcount++;
+ }
+
+ if ($failedcount > 0)
+ header("Location: " . getFullPath("index.php?message=Your+message+has+been+sent+to+$recipcount+recipient(s).+There+were+$failedcount+failures."));
+ else
+ header("Location: " . getFullPath("index.php?message=Your+message+has+been+sent+to+$recipcount+recipient(s)."));
exit;
}
diff --git a/src/mylist.php b/src/mylist.php
index 7cf4bcc..468ff03 100644
--- a/src/mylist.php
+++ b/src/mylist.php
@@ -20,41 +20,50 @@ $opt = $smarty->opt();
session_start();
if (!isset($_SESSION["userid"])) {
- header("Location: " . getFullPath("login.php"));
+ header("Location: " . getFullPath("login.php") . "?from=mylist.php");
exit;
}
else {
$userid = $_SESSION["userid"];
}
-if (empty($_GET["sort"]))
- $sort = "source";
-else
- $sort = $_GET["sort"];
-
-switch($sort) {
- case "category":
- $sortby = "category, source, price";
- break;
- case "description":
- $sortby = "description, price";
- break;
- case "ranking":
- $sortby = "rankorder DESC, source, price";
- break;
- case "source":
- $sortby = "source, category, rankorder DESC";
- break;
- case "price":
- $sortby = "quantity * price, category, source";
- break;
- default:
- $sortby = "rankorder DESC, source, price";
+if (!empty($_GET["sortdir"])) {
+ $sortdir = strtoupper(trim($_GET["sortdir"])) == "DESC" ? "DESC" : "ASC";
+} else {
+ $sortdir = "ASC";
+}
+if (empty($_GET["sort"])) {
+ $sortby = "name";
+ $sort = "name";
+} else {
+ $sort = filter_var(trim($_GET["sort"], FILTER_SANITIZE_STRING));;
+ $sort = htmlspecialchars($sort, ENT_QUOTES, 'UTF-8');
+ switch($sort) {
+ case "category":
+ $sortby = "category $sortdir, source, price";
+ $sort = "category";
+ break;
+ case "name":
+ $sortby = "name $sortdir, price";
+ $sort = "name";
+ break;
+ case "source":
+ $sortby = "source $sortdir, category, rankorder";
+ $sort = "source";
+ break;
+ case "price":
+ $sortby = "quantity * price $sortdir, category, source";
+ $sort = "price";
+ break;
+ default:
+ $sortby = "rankorder $sortdir, source, price";
+ $sort = "ranking";
+ }
}
try {
// not worried about SQL injection since $sortby is calculated above.
- $stmt = $smarty->dbh()->prepare("SELECT description, source, price, i.comment, i.quantity, i.quantity * i.price AS total, rendered, c.category " .
+ $stmt = $smarty->dbh()->prepare("SELECT name, description, source, price, r.title as ranktitle, i.comment, i.quantity, i.quantity * i.price AS total, rendered, c.category " .
"FROM {$opt["table_prefix"]}items i " .
"INNER JOIN {$opt["table_prefix"]}users u ON u.userid = i.userid " .
"INNER JOIN {$opt["table_prefix"]}ranks r ON r.ranking = i.ranking " .
@@ -77,6 +86,8 @@ try {
$shoplist[] = $row;
}
+ $smarty->assign('sort', $sort);
+ $smarty->assign('sortdir', $sortdir);
$smarty->assign('shoplist', $shoplist);
$smarty->assign('totalprice', formatPrice($totalprice, $opt));
$smarty->assign('itemcount', $itemcount);
diff --git a/src/profile.php b/src/profile.php
index c5a7404..dc51cdb 100644
--- a/src/profile.php
+++ b/src/profile.php
@@ -21,7 +21,7 @@ $opt = $smarty->opt();
session_start();
if (!isset($_SESSION["userid"])) {
- header("Location: " . getFullPath("login.php"));
+ header("Location: " . getFullPath("login.php") . "?from=profile.php");
exit;
}
else {
@@ -31,7 +31,7 @@ else {
$action = "";
if (!empty($_POST["action"])) {
$action = $_POST["action"];
-
+
if ($action == "changepwd") {
$newpwd = $_POST["newpwd"];
@@ -64,7 +64,7 @@ if (!empty($_POST["action"])) {
$stmt->bindParam(4, $show_helptext, PDO::PARAM_BOOL);
$stmt->bindParam(5, $comment, PDO::PARAM_STR);
$stmt->bindParam(6, $userid, PDO::PARAM_INT);
-
+
$stmt->execute();
$_SESSION["fullname"] = $fullname;
diff --git a/src/ranks.php b/src/ranks.php
index 051f9fa..977cce2 100644
--- a/src/ranks.php
+++ b/src/ranks.php
@@ -20,7 +20,7 @@ $opt = $smarty->opt();
session_start();
if (!isset($_SESSION["userid"])) {
- header("Location: " . getFullPath("login.php"));
+ header("Location: " . getFullPath("login.php") . "?from=ranks.php");
exit;
}
else if ($_SESSION["admin"] != 1) {
@@ -31,47 +31,68 @@ else {
$userid = $_SESSION["userid"];
}
if (!empty($_GET["message"])) {
- $message = $_GET["message"];
+ $message = filter_var(trim($_GET["message"], FILTER_SANITIZE_STRING));;
+ $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
}
+if (isset($_GET["ranking"])) {
+ $ranking = filter_var(trim($_GET["ranking"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($ranking, FILTER_SANITIZE_NUMBER_INT) === false || $ranking == "" || !is_numeric($ranking) || $ranking < 0) {
+ die("Invalid ranking ({$_GET["ranking"]})");
+ }
+}
+
+if (isset($_GET["rankorder"])) {
+ $rankorder = filter_var(trim($_GET["rankorder"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($rankorder, FILTER_SANITIZE_NUMBER_INT) === false || $rankorder == "" || !is_numeric($rankorder) || $rankorder < 0) {
+ die("Invalid rankorder ({$_GET["rankorder"]})");
+ }
+}
+
+$haserror = false;
+$error_message = "";
+
$action = isset($_GET["action"]) ? $_GET["action"] : "";
if ($action == "insert" || $action == "update") {
/* validate the data. */
- $title = trim($_GET["title"]);
- $rendered = trim($_GET["rendered"]);
-
- $haserror = false;
+ $title = filter_var(trim($_GET["title"], FILTER_SANITIZE_STRING));;
+ $rendered = filter_var(trim($_GET["rendered"], FILTER_SANITIZE_STRING));;
+
if ($title == "") {
$haserror = true;
- $title_error = "A title is required.";
+ $error_message = trim("$error_message A title is required.");
+ $title_error = true;
}
if ($rendered == "") {
$haserror = true;
- $rendered_error = "HTML is required.";
+ $error_message = trim("$error_message HTML is required.");
+ $rendered_error = true;
}
}
if ($action == "delete") {
/* first, NULL all ranking FKs for items that use this rank. */
$stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}items SET ranking = NULL WHERE ranking = ?");
- $stmt->bindValue(1, (int) $_GET["ranking"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $ranking, PDO::PARAM_INT);
$stmt->execute();
$stmt = $smarty->dbh()->prepare("DELETE FROM {$opt["table_prefix"]}ranks WHERE ranking = ?");
- $stmt->bindValue(1, (int) $_GET["ranking"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $ranking, PDO::PARAM_INT);
$stmt->execute();
-
+
header("Location: " . getFullPath("ranks.php?message=Rank+deleted."));
exit;
}
else if ($action == "promote") {
$stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}ranks SET rankorder = rankorder + 1 WHERE rankorder = ? - 1");
- $stmt->bindValue(1, (int) $_GET["rankorder"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $rankorder, PDO::PARAM_INT);
$stmt->execute();
$stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}ranks SET rankorder = rankorder - 1 WHERE ranking = ?");
- $stmt->bindValue(1, (int) $_GET["ranking"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $ranking, PDO::PARAM_INT);
$stmt->execute();
header("Location: " . getFullPath("ranks.php?message=Rank+promoted."));
@@ -79,19 +100,19 @@ else if ($action == "promote") {
}
else if ($action == "demote") {
$stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}ranks SET rankorder = rankorder - 1 WHERE rankorder = ? + 1");
- $stmt->bindValue(1, (int) $_GET["rankorder"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $rankorder, PDO::PARAM_INT);
$stmt->execute();
- $stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}ranks SET rankorder = rankorder + 1 WHERE ranking = ?");
- $stmt->bindValue(1, (int) $_GET["ranking"], PDO::PARAM_INT);
+ $stmt = $smarty->dbh()->prepare("UPDATE {$opt["table_prefix"]}ranks SET rankorder = rankorder + 1 WHERE ranking = ?");
+ $stmt->bindValue(1, (int) $ranking, PDO::PARAM_INT);
$stmt->execute();
-
+
header("Location: " . getFullPath("ranks.php?message=Rank+demoted."));
- exit;
+ exit;
}
else if ($action == "edit") {
$stmt = $smarty->dbh()->prepare("SELECT title, rendered FROM {$opt["table_prefix"]}ranks WHERE ranking = ?");
- $stmt->bindValue(1, (int) $_GET["ranking"], PDO::PARAM_INT);
+ $stmt->bindValue(1, (int) $ranking, PDO::PARAM_INT);
$stmt->execute();
if ($row = $stmt->fetch()) {
$title = $row["title"];
@@ -114,7 +135,7 @@ else if ($action == "insert") {
$stmt->bindParam(2, $rendered, PDO::PARAM_STR);
$stmt->bindParam(3, $rankorder, PDO::PARAM_INT);
$stmt->execute();
-
+
header("Location: " . getFullPath("ranks.php?message=Rank+added."));
exit;
}
@@ -127,11 +148,11 @@ else if ($action == "update") {
"WHERE ranking = ?");
$stmt->bindParam(1, $title, PDO::PARAM_STR);
$stmt->bindParam(2, $rendered, PDO::PARAM_STR);
- $stmt->bindValue(3, (int) $_GET["ranking"], PDO::PARAM_INT);
+ $stmt->bindValue(3, (int) $ranking, PDO::PARAM_INT);
$stmt->execute();
-
+
header("Location: " . getFullPath("ranks.php?message=Rank+updated."));
- exit;
+ exit;
}
}
else {
@@ -160,7 +181,10 @@ $smarty->assign('rendered', $rendered);
if (isset($rendered_error)) {
$smarty->assign('rendered_error', $rendered_error);
}
-$smarty->assign('ranking', isset($_GET["ranking"]) ? (int) $_GET["ranking"] : "");
+$smarty->assign('ranking', isset($ranking) ? (int) $ranking : "");
$smarty->assign('haserror', isset($haserror) ? $haserror : false);
+if ($error_message != "") {
+ $smarty->assign('error_message', $error_message);
+}
$smarty->display('ranks.tpl');
?>
diff --git a/src/receive.php b/src/receive.php
index 33f6ada..31ad06b 100644
--- a/src/receive.php
+++ b/src/receive.php
@@ -20,7 +20,7 @@ $opt = $smarty->opt();
session_start();
if (!isset($_SESSION["userid"])) {
- header("Location: " . getFullPath("login.php"));
+ header("Location: " . getFullPath("login.php") . "?from=receive.php");
exit;
}
else {
@@ -28,7 +28,30 @@ else {
}
$action = (!empty($_GET["action"]) ? $_GET["action"] : "");
-$itemid = (int) $_GET["itemid"];
+if (isset($_GET["itemid"])) {
+ $itemid = filter_var(trim($_GET["itemid"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($itemid, FILTER_SANITIZE_NUMBER_INT) === false || $itemid == "" || !is_numeric($itemid) || $itemid < 0) {
+ die("Invalid itemid ({$_GET["itemid"]})");
+ }
+ $itemid = (int) $itemid;
+}
+
+if (isset($_GET["buyer"])) {
+ $buyer = filter_var(trim($_GET["buyer"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($buyer, FILTER_SANITIZE_NUMBER_INT) === false || $buyer == "" || !is_numeric($buyer) || $buyer < 0) {
+ die("Invalid buyer ({$_GET["buyer"]})");
+ }
+}
+
+if (isset($_GET["quantity"])) {
+ $quantity = filter_var(trim($_GET["quantity"]), FILTER_SANITIZE_NUMBER_INT);
+
+ if (filter_var($quantity, FILTER_SANITIZE_NUMBER_INT) === false || $quantity == "" || !is_numeric($quantity) || $quantity < 0) {
+ die("Invalid quantity ({$_GET["quantity"]})");
+ }
+}
// get details. is it our item? is this a single-quantity item?
try {
@@ -65,13 +88,13 @@ try {
}
else if ($action == "receive") {
// $actual will be a negative number, so let's flip it.
- $actual = -adjustAllocQuantity($itemid, (int) $_GET["buyer"], 1, -1 * (int) $_GET["quantity"], $smarty->dbh(), $smarty->opt());
-
- if ($actual < (int) $_GET["quantity"]) {
+ $actual = -adjustAllocQuantity($itemid, (int) $buyer, 1, -1 * (int) $quantity, $smarty->dbh(), $smarty->opt());
+
+ if ($actual < (int) $quantity) {
// $userid didn't have that many bought, so some might have been reserved.
- $actual += -adjustAllocQuantity($itemid,(int) $_GET["buyer"],0,-1 * ((int) $_GET["quantity"] - $actual), $smarty->dbh(), $smarty->opt());
+ $actual += -adjustAllocQuantity($itemid,(int) $buyer,0,-1 * ((int) $quantity - $actual), $smarty->dbh(), $smarty->opt());
}
-
+
if ($actual == $quantity) {
// now they're all gone.
deleteImageForItem($itemid, $smarty->dbh(), $smarty->opt());
@@ -86,7 +109,7 @@ try {
$stmt->bindParam(2, $itemid, PDO::PARAM_INT);
$stmt->execute();
}
-
+
header("Location: " . getFullPath("index.php?message=Item+marked+as+received."));
exit;
}
diff --git a/src/setup.php b/src/setup.php
index 57fb95e..520751f 100644
--- a/src/setup.php
+++ b/src/setup.php
@@ -48,7 +48,7 @@ if (isset($_POST["action"])) {
$stmt = dbh($opt)->prepare("INSERT INTO {$opt["table_prefix"]}families(familyname) VALUES(?)");
$stmt->bindParam(1, $familyname, PDO::PARAM_STR);
$stmt->execute();
-
+
// 2. get the familyid.
$stmt = dbh($opt)->prepare("SELECT MAX(familyid) AS familyid FROM {$opt["table_prefix"]}families");
$stmt->execute();
@@ -188,7 +188,7 @@ else {
$smarty = new MySmarty();
$smarty->testInstall();
?>
-