Hierbij mijn oplossing zodat de zoekende GoT-er er wellicht ook wat aan heeft. De oplossing is gebouwd rondt de volgende visie:
- Entities horen niet in de database
- Data uit de database wordt voor de veiligheid in elke view omgezet naar de bijbehorende entities
- View variabelen worden omgezet naar de bijbehorende entities
- Voor maximale veiligheid ben ik gegaan voor het opt-out scenario: entities worden standaard omgezet in de views, als er geen entities nodig zijn (bijv. in form fields) is er een functie call nodig die de entities decodeert.
Om het omzetten te automatiseren heb ik de core moeten extenden. Allereerst een custom loader:
FILE: MY_loader.php (in application/core):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| <?php
/**
* Class extension that auto replaces all view vars with their htmlentities
*/
class MY_Loader extends CI_Loader {
/**
* @param $view
* @param array $vars
* @param bool $return
* @return Page
*/
public function view($view, $vars = array(), $return = FALSE) {
if(is_array($vars)) {
$vars = $this->_prep_output($vars);
}
return parent::view($view, $vars, $return);
}
/**
* @param $array
* @return array
*/
private function _prep_output($array) {
foreach($array as $key => $value) {
if(is_array($value)) {
$array[$key] = $this->_prep_output($value);
}
elseif (!is_object($value)) {
$array[$key] = htmlentities($value, ENT_QUOTES, "UTF-8");
}
}
return $array;
}
/**
* @param string $params
* @param bool $return
* @param null $active_record
* @return bool
*/
function database($params = '', $return = FALSE, $active_record = NULL) {
// Grab the super object
$CI =& get_instance();
// Do we even need to load the database class?
if (class_exists('CI_DB') AND $return == FALSE AND $active_record == NULL AND isset($CI->db) AND is_object($CI->db)) {
return FALSE;
}
require_once(BASEPATH.'database/DB'.EXT);
// Load the DB class
$db =& DB($params, $active_record);
$my_driver = config_item('subclass_prefix').'DB_'.$db->dbdriver.'_driver';
$my_driver_file = APPPATH.'core/'.$my_driver.EXT;
if (file_exists($my_driver_file)) {
require_once($my_driver_file);
$db = new $my_driver(get_object_vars($db));
}
if ($return === TRUE) {
return $db;
}
// Initialize the db variable. Needed to prevent
// reference errors with some configurations
$CI->db = '';
$CI->db = $db;
}
} |
In deze code gebeuren 2 dingen:
- View variabelen die geen object zijn worden omgezet naar entities
- Een custom db extension wordt geinitialiseerd i.p.v. de native db class van CodeIgniter
Wat dit bereikt:
-
Alle variabelen in views die geen object zijn worden omgezet naar de bijbehorende entities.
De meest voorkomende objecten in CodeIgniter views zijn databse resultaten. Ook deze laat ik geautomatiseerd om zetten in views:
FILE: MY_DB_mysql_driver.php (in application/core):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_DB_mysql_driver extends CI_DB_mysql_driver {
function load_rdriver()
{
$driver = 'CI_DB_'.$this->dbdriver.'_result';
if ( ! class_exists($driver))
{
include_once(BASEPATH.'database/DB_result'.EXT);
include_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result'.EXT);
}
$CI =& get_instance();
$my_driver = config_item('subclass_prefix').'DB_'.$this->dbdriver.'_result';
$my_driver_file = APPPATH.'core/'.$my_driver.EXT;
if (file_exists($my_driver_file))
{
require_once($my_driver_file);
return $my_driver;
}
else
{
return $driver;
}
}
}
?> |
In deze code gebeurt niets anders dan een andere result klasse te definiëren dan de native klasse.
FILE: MY_DB_mysql_result (in application/core):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_DB_mysql_result extends CI_DB_mysql_result {
/**
* @param string $type
* @return array|mixed
*/
public function view_result($type = 'object') {
$objects = parent::result($type);
foreach($objects as $key => $object) {
$vars = get_object_vars($object);
foreach($vars as $key => $value) {
$object->$key = entities($value);
$objects[$key] = $object;
}
}
return $objects;
}
/**
* @return array|string
*/
public function view_result_array() {
return entities(parent::result_array());
}
/**
* @param int $n
* @param string $type
* @return mixed
*/
public function view_row($n = 0, $type = 'object') {
$object = parent::row($n, $type);
$vars = get_object_vars($object);
foreach($vars as $key => $value) {
$object->$key = entities($value);
}
return $object;
}
/**
* @param int $n
* @return array|string
*/
public function view_row_array($n = 0) {
return entities(parent::row_array($n));
}
}
?> |
In deze code wordt voor elke result functie die CodeIgniter kent een daarbij horende view functie gedefinieerd die gebruikt moet worden in de view loops. De view_ functies doen exact hetzelfde als de originele resultaat functies, met het verschil dat ze entities omzetten.
Tot slot heb ik nog een extension van de security helper gemaakt die functies bevat om handmatig entities om te zetten (bijv. form input values):
FILE: MY_security_helper (in application/helpers):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
| <?php
/**
* @param $array
* @return array|string
*/
function entities($array) {
if(is_array($array)) {
array_walk_recursive($array, '_prep_entities');
}
else {
$array = htmlentities($array, ENT_QUOTES, "UTF-8");
}
return $array;
}
/**
* @param $array
* @return array|string
*/
function no_entities($array) {
if(is_array($array)) {
array_walk_recursive($array, '_rem_entities');
}
else {
$array = html_entity_decode($array, ENT_QUOTES, "UTF-8");
}
return $array;
}
/**
* @param $item
* @param $key
* @return void
*/
function _prep_entities(&$item, $key) {
$item = htmlentities($item, ENT_QUOTES, "UTF-8");
}
/**
* @param $item
* @param $key
* @return void
*/
function _rem_entities(&$item, $key) {
$item = html_entity_decode($item, ENT_QUOTES, "UTF-8");
}
?> |