# Escaping

<span>How to properly escape html/js code in Smarty templates and PHP files</span>

# Introduction

Starting with vtenext version 26.01, all variables outputted by Smarty templates (for example `{$VARIABLE}` ) by default have all applicable characters are converted to html `&...;` notation. For instance, the string `"nice & 'smooth' à > è"` is converted to `"nice &amp; &039;smooth&039; &agrave; &gt; &egrave;"`

The conversion is done with the `htmlentities` function, without double encoding existing entities.

The reason of this change is to reduce as much as possible exposure to XSS attacks, since it was extremely difficult to track every possible variable in templates and ensure it was properly escaped.

There are of course some exceptions on the escaping and some edge cases that should be understood. The next chapter presents the rules to follow to write simple and secure code.

# Escaping rules

##### 1. Avoid html code in php

Avoid generating html code directly in php, or outputting it directly. If possible use Smarty templates. Exceptions can be made for very short snippets, see paragraph 3 for how to handle them.

<table border="1" id="bkmrk-" style="border-collapse: collapse; width: 108.929%; height: 419px;"><colgroup><col style="width: 44.4577%;"></col><col style="width: 55.5423%;"></col></colgroup><thead><tr><td class="align-center" colspan="2">**Examples**  
</td></tr></thead><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;"><p class="callout success">**Good**</p>

```php
$name = "John & friends";
$smarty->assign("NAME", $name);
```

And in smarty:

```smarty
{* & will be converted to &amp; *}
<div>{$NAME}</div>
```

Will output:

```html
<div>John &amp; friends</div>
```

</td><td style="height: 29.7969px;"><p class="callout danger">**Bad**: html generated in php</p>

```php
$name = "John & friends";
// the "div" will be escaped
$string = "<div>{$name}</div>";
$smarty->assign("TEXT", $string);
```

 And in smarty:

```smarty
{$TEXT}
```

Will output:

```html
&lt;div&gt;John &amp; friends&lt;/div&gt;
```

<p class="callout danger">**Bad**: output via echo</p>

```php
$name = "John & friends";
$string = "<div>{$name}</div>";

// by using echo on the raw string,
// we introduce a XSS if $name comes from user input

echo $string;
```

</td></tr></tbody></table>

##### 2. Reading from database

Avoid using `query_result` and `fetchByAssoc` without the `-1, false` 2nd and 3rd parameters.

This is because the those functions already do html conversion, which is the wrong place to do it, since the result may have to be processed more before being displayed by the browser (or not displayed at all in a browser if the result is for a REST API).

<table border="1" id="bkmrk-examples-good-%C2%A0-%C2%A0-%24r" style="border-collapse: collapse; width: 108.929%; height: 419px;"><colgroup><col style="width: 50.0596%;"></col><col style="width: 50.0596%;"></col></colgroup><thead><tr><td class="align-center" colspan="2">**Examples**  
</td></tr></thead><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;"><p class="callout success">**Good**</p>

```
$res = $adb->query("SELECT helpinfo FROM vte_field");

$first = $adb->query_result_no_html($res, 0, 'helpinfo');
```

</td><td style="height: 29.7969px;"><p class="callout danger">**Bad**: helpinfo is converted!</p>

```
$res = $adb->query("SELECT helpinfo FROM vte_field");

$first = $adb->query_result($res, 0, 'helpinfo');
```

</td></tr><tr style="height: 27.7969px;"><td style="height: 27.7969px;"><p class="callout success">**Good**</p>

```
$res = $adb->query("SELECT helpinfo FROM vte_field");

while ($row = $adb->fetchByAssoc($res, -1, false)) {
  // ...
}
```

</td><td style="height: 27.7969px;"><p class="callout danger">**Bad**: helpinfo is converted!</p>

```
$res = $adb->query("SELECT helpinfo FROM vte_field");
while ($row = $adb->fetchByAssoc($res)) {
  // ...
}
```

</td></tr></tbody></table>

##### 3. Generating html in php

Sometimes it's really inevitable to generate html code in php (legacy code, or existing developments...), so in this case, to avoid a double conversion when Smarty processes the template, we should use the `\Vtenext\Types\HtmlString` class to wrap the html string. This class is a simple wrapper around a string, that doesn't get automatically converted by Smarty. Remember, that in this case, all the html conversion **must be done** in php using the `VStr::toHtml` or `VStr::toHtmlAttr` methods.

Example:

```php
// for brevity:
use \Vtenext\Types\HtmlString;

$name = "John Connor";
$url = "index.php?module=aaa&action=".urlencode($_REQUEST['param']); // danger here: user input!

// building the link with manual conversion
$link = "<a href='".VStr::toHtmlAttr($url)."'>".VStr::toHtml($name)."</a>";

// wrapping it in HtmlString
$link = new HtmlString($link);

$smarty->assign("LINK", $link); // this will NOT be escaped!! Be sure all parameters are properly escaped!!
```

There are also 2 utility methods to build html string safely, `HtmlString::build` and `HtmlString::buildSmarty`. Let's see some examples:

```php
// with build(), every instance of ### is replaced with one of the parameters,
// and escaped for html. The resulting string is safe for raw inclusion in templates
$icon = HtmlString::build('<i class="vteicon md-sm" title="###" style="color: white;">settings</i>', [trans('LBL_AREAS_SETTINGS')]);

# even when reading from $_REQUEST, we don't have XSS here
$errStr = HtmlString::build("<font class='error'>Error: ###</font>", RH::r('error_string'));

// buildSmarty takes a smarty template in string form and does the standard conversion:
$tpl = '
  <input class="crmbutton" onclick="myFunction(\'{$module}\', {$recordid}, \'{$entityName}\')" type="button"
  value="{"LBL_LINK_ACTION"|trans}">';

$params = [
	'module' => $currentModule,
	'recordid' => intval($recordid),
	'entityName' => VStr::toJs($entityName, ''), // js stuff must be explicitely escaped
];
$html =  HtmlString::buildSmarty($tpl, $params);

```

##### 4. Assigning to Smarty

Assign the variables normally, without using decode\_html, htmlspecialchars, htmlentities or other conversion functions.

<table border="1" id="bkmrk-examples-good-%C2%A0-%C2%A0-%24s" style="border-collapse: collapse; width: 108.929%; height: 419px;"><colgroup><col style="width: 50.0596%;"></col><col style="width: 50.0596%;"></col></colgroup><thead><tr><td class="align-center" colspan="2">**Examples**  
</td></tr></thead><tbody><tr style="height: 29.7969px;"><td style="height: 29.7969px;"><p class="callout success">**Good**</p>

```sma
$string = "my nice text with < and >";
$smarty->assign("VAR", $string);

```

And in smarty:

```smarty
{* < and > will be converted *}
<div>{$VAR}</div>
```

</td><td style="height: 29.7969px;"><p class="callout danger">**Bad**: no need to convert 2 times</p>

```sma
$string = "my nice text with < and >";
$smarty->assign("VAR", htmlentities($string));

```

 And in smarty:

```smarty
{* still work the same, 
since double_encoding is false
but not a good idea anyway *}
<div>{$VAR}</div>
```

 </td></tr></tbody></table>

##### 5. Inside Smarty templates (html)

Output variables as they are, no additional escaping needed in html. For variables inside javascript code (ex: in onclick attributes) see the next paragraph.

##### 6. Inside Smarty templates (javascript)

Javacript code, inside Smarty templates, delimited by &lt;script&gt; tags, has a special handling. Inside these blocks, the default html conversion is not done, instead, the following happens:

1. If the variable to replace begins with `[` or `{`, no escaping is done
2. Otherwise, the variable is escaped with `VStr::toJs` (which does a addslashes)

For examples, if in PHP we have:

```php
$arr = [1,2,3];
$obj = ['name' => 'test'];

// no need of js escaping here
$smarty->assign("STR", "test <tag> 'quote' end");

// this is the preferred way to pass complex types, as they are!
$smarty->assign("ARR", $arr);
$smarty->assign("OBJ", $obj);

// for legacy code it's acceptable to have this
$smarty->assign("JSARR", json_encode($arr));
$smarty->assign("JSOBJ", json_encode($obj));

// AVOID to build js structures with string manipulation in PHP!!
```

then in the template we can use:

```html
<script>
  // both double quotes and single quotes can be used, they are both escaped!
  var str1 = '{$STR}'; // will become test <tag> \'quote\' end
  var str2 = "{$STR}";

  // the preferred way is to use json_encode for complex types
  var arr = {$ARR|json_encode};
  var obj = {$OBJ|json_encode};

  // but in case something is already in json form:
  var arr = {$JSARR}; // this WILL NOT be escaped!
  var obj = {$JSOBJ}; // also this one
  
</script>
```

Outside of `<script>` tags, the standard html conversion is done, so in case of javascript code in attributes (ex: onclick handlers), manual escaping is still necessary, for example:

```smarty
{* using escape in "javascript" mode *}
<span onclick="myFunction('{$PARAM|escape:"javascript"}')">Link</span>

{* using out VStr::toJs method *}
<span onclick="myFunction2('{VStr::toJs($PARAM)}')">Link2 </span>

{* for urls inside js, use "url" mode before the js encoding *}
<span onclick="location.href='index.php?mode={$MODPARAM|escape:"url"|escape:"javascript"}';">Link 3</span>
```

##### 7. Skipping the conversion

Sometimes it's necessary to override the default conversion and output the raw variable as is. This can be achieved in two ways:

1. By using `nofilter`:  
      
    ```smarty
    <span>{$RAW_VAR nofilter}</span>
    ```
2. By using the modifier `rawhtml` (will convert the string to HtmlString, thus avoiding the conversion)  
      
    ```smarty
    <span>{$RAW_VAR|rawhtml}</span>
    ```

##### 8. Special cases: labels

When using labels in templates (ex: `"LBL_SOMETHING"|trans` or `$APP.LBL_SOMETHING`), html chars are converted. Some labels, though, contains html code, and in this case they should be used with the `rawhtml` or `nofilter` modifiers.

##### 9. Special cases: {capture}

When using `{capture}` in templates, the content is saved in a variable. If that variable is then outputted, the content is escaped, which is usually unwanted since the content is html. In this case, the `rawhtml` or `nofilter` modifier must be used.

For example, if the capture block is:

```smarty
{capture assign="content"}
<div> Hello {$FRIEND}</div> {* $FRIEND will be converted to html entities *}
{/capture}
```

It should be used with:

```smarty
<h2>{$content|rawhtml}</h2>
```

or

```smarty
<h2>{$content nofilter}</h2>
```

or

```smarty
{include file="NoLoginMsg.tpl" BODY=$content|rawhtml}
```

# Cheat sheet

Quick reference if you just need to know how to escape stuff!

**Do's and Don'ts**

- Use only `query_result_no_html` and `fetchByAssoc(..., -1, false)` or `fetchByAssocNoHtml`, we don't want that pesky `to_html` function to be called
- Do not generate html strings in php, use templates or `HtmlString::build`
- Do not echo html code in PHP, use Smarty
- Do not use `VStr::toJsAttr` method
- Do not try to build js code from PHP, use .js files or `<script>` tags in templates
- Do not use `html_entity_decode`, `htmlentities`, `htmlspecialchars`, `addslashes`, it's probably not needed (unless you are working on legacy code)
- Do not use `to_html`, `from_html`, `decode_html` , these were always a bad idea

**How to's:**

<table border="1" id="bkmrk-how-do-i-handle...-." style="border-collapse: collapse; width: 100%; height: 681.453px;"><colgroup><col style="width: 9.77354%;"></col><col style="width: 18.9511%;"></col><col style="width: 71.2753%;"></col></colgroup><thead><tr style="height: 29.7969px;"><td style="height: 29.7969px;">**In**</td><td style="height: 29.7969px;">**How do I handle... ?**</td><td style="height: 29.7969px;">**... like this:**</td></tr></thead><tbody><tr style="height: 46.5938px;"><td rowspan="4" style="height: 316.312px;">Smarty, html code

</td><td style="height: 46.5938px;">standard variable</td><td style="height: 46.5938px;">`{$VARIABLE}`</td></tr><tr style="height: 46.5938px;"><td style="height: 46.5938px;">variable, but it's a HtmlString</td><td style="height: 46.5938px;">`{$VARIABLE}`</td></tr><tr style="height: 63.3906px;"><td style="height: 63.3906px;">variable, but it's a string and already html</td><td style="height: 63.3906px;">`{$VARIABLE nofilter}`

or

`{$VARIABLE|rawhtml}`

</td></tr><tr style="height: 159.734px;"><td style="height: 159.734px;">`{capture}` blocks</td><td style="height: 159.734px;">```smarty
{capture assign="capname"}
  <div>.... html code {$VARIABLE} </div>
{capture}

{$capname nofilter}
```

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;"></td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td></tr><tr style="height: 63.375px;"><td rowspan="3" style="height: 122.969px;">Smarty,

inside `<script>`

  
</td><td style="height: 63.375px;">string variable</td><td style="height: 63.375px;">`var myvar = '{$VARIABLE}';`</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">object or array variable</td><td style="height: 29.7969px;">`var mylist = {$VARIABLE|json_encode};`</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">string inside url</td><td style="height: 29.7969px;">`var url = "index.php?module={$VARIABLE|escape:"url"}";`

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td><td style="height: 29.7969px;">  
</td></tr><tr style="height: 63.3906px;"><td rowspan="2" style="height: 63.3906px;">Smarty,

js in attributes

</td><td style="height: 63.3906px;">string variable</td><td style="height: 63.3906px;">```smarty
{* using escape in "javascript" mode *}
<span onclick="myFunction('{$PARAM|escape:"javascript"}')">Link</span>

{* using out VStr::toJs method *}
<span onclick="myFunction2('{VStr::toJs($PARAM)}')">Link2 </span>
```

</td></tr><tr style="height: 29.7969px;"><td style="height: 29.7969px;">string in url</td><td style="height: 29.7969px;">```smarty
<span onclick="location.href='index.php?mode={$MODPARAM|escape:"url"|escape:"javascript"};>Link 3</span>
```

</td></tr></tbody></table>