Unverified Commit 552ae07e authored by Patrick Figel's avatar Patrick Figel
Browse files

dev/core#1328 - Clarify non-DAO output encoding strategy

CiviCRM's output encoding strategy offers quite a few footguns. This
attempts to make it easier to understand which output encoding strategy
is necessary in which scenario when working with Smarty templates.
parent 235a9ca0
......@@ -122,7 +122,7 @@ CiviCRM's strategy is as follows:
1. For rich text, [purify inputs](inputs.md#input-purification)
* Outputs:
1. HTML:
* Do *not* perform HTML encoding for [data between tags](outputs.md#between-tags)
* *Sometimes* perform HTML encoding for [data between tags](outputs.md#between-tags) (depending on the data source)
* *Do* perform HTML encoding for [data within attributes](outputs.md#in-attributes)
1. SQL: [validate and encode](outputs.md#sql)
1. Shell: [validate and encode](outputs.md#shell)
......
......@@ -6,29 +6,57 @@ Untrusted data placed in HTML must be [encoded](index.md#encoding) for HTML outp
### Between tags {:#db-between-tags}
Whether data needs to be output encoded depends primarily on the data source:
#### Database data between tags {:#db-between-tags}
Data which comes out of MySQL has already been [partially encoded for HTML output](inputs.md#input-encoding). This means that when you place this data between HTML tags, you don't need to perform any output encoding. For example:
Data which comes *directly* out of MySQL has already been [partially encoded for HTML output](inputs.md#input-encoding). This means that when you place this data between HTML tags, you don't need to perform any output encoding. For example:
```php
// in page class
$dao = new CRM_Core_DAO();
$dao->query('SELECT display_name FROM civicrm_contact');
if ($dao->fetch()) {
// set template variable
$this->assign('displayName', $displayName);
}
```
```html
<!-- in template -->
<div>{$displayName}</div>
```
#### Direct user input between tags {:#inputs-between-tags}
#### API data or direct user input between tags {:#inputs-between-tags}
Here we have a bit of a grey area where CiviCRM does not have a consistent approach. If untrusted inputs are placed into HTML before being saved to the database, you need to ensure to perform HTML output encoding *at some point*.
You can perform the output encoding in PHP as follows:
HTML output encoding needs to be performed *at some point* for any data that is fetched via the API as well as any untrusted user input that is placed into HTML before being saved to the database. The recommended approach is to perform output encoding in the template:
```php
$userInput = htmlentities($userInput);
// in page class
$contacts = \Civi\Api4\Contact::get()
->addSelect('display_name')
->execute();
foreach ($contacts as $contact) {
$this->assign('displayName', $contact['display_name']);
}
```
Or you can perform the output encoding in Smarty as follows:
```html
<div>{$userInput|escape}</div>
```
<!-- in template -->
<div>{$displayName|escape}</div>
```
Alternatively, you can encode before passing the value to the template:
```php
// in page class
$contacts = \Civi\Api4\Contact::get()
->addSelect('display_name')
->execute();
foreach ($contacts as $contact) {
$this->assign('displayName', htmlentities($contact['display_name']));
}
```
!!! tip
Be wary of using user input in *error messages*. This is a common scenario wherein untrusted user input can end up in HTML with no HTML output encoding.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment