source: Dev/branches/cakephp/cake/libs/sanitize.php @ 126

Last change on this file since 126 was 126, checked in by fpvanagthoven, 14 years ago

Cakephp branch.

File size: 9.3 KB
Line 
1<?php
2App::import('Model', 'ConnectionManager');
3/**
4 * Washes strings from unwanted noise.
5 *
6 * Helpful methods to make unsafe strings usable.
7 *
8 * PHP versions 4 and 5
9 *
10 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
11 * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
12 *
13 * Licensed under The MIT License
14 * Redistributions of files must retain the above copyright notice.
15 *
16 * @copyright     Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
17 * @link          http://cakephp.org CakePHP(tm) Project
18 * @package       cake
19 * @subpackage    cake.cake.libs
20 * @since         CakePHP(tm) v 0.10.0.1076
21 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
22 */
23
24/**
25 * Data Sanitization.
26 *
27 * Removal of alpahnumeric characters, SQL-safe slash-added strings, HTML-friendly strings,
28 * and all of the above on arrays.
29 *
30 * @package       cake
31 * @subpackage    cake.cake.libs
32 */
33class Sanitize {
34
35/**
36 * Removes any non-alphanumeric characters.
37 *
38 * @param string $string String to sanitize
39 * @param array $allowed An array of additional characters that are not to be removed.
40 * @return string Sanitized string
41 * @access public
42 * @static
43 */
44        function paranoid($string, $allowed = array()) {
45                $allow = null;
46                if (!empty($allowed)) {
47                        foreach ($allowed as $value) {
48                                $allow .= "\\$value";
49                        }
50                }
51
52                if (is_array($string)) {
53                        $cleaned = array();
54                        foreach ($string as $key => $clean) {
55                                $cleaned[$key] = preg_replace("/[^{$allow}a-zA-Z0-9]/", '', $clean);
56                        }
57                } else {
58                        $cleaned = preg_replace("/[^{$allow}a-zA-Z0-9]/", '', $string);
59                }
60                return $cleaned;
61        }
62
63/**
64 * Makes a string SQL-safe.
65 *
66 * @param string $string String to sanitize
67 * @param string $connection Database connection being used
68 * @return string SQL safe string
69 * @access public
70 * @static
71 */
72        function escape($string, $connection = 'default') {
73                $db =& ConnectionManager::getDataSource($connection);
74                if (is_numeric($string) || $string === null || is_bool($string)) {
75                        return $string;
76                }
77                $string = substr($db->value($string), 1);
78                $string = substr($string, 0, -1);
79                return $string;
80        }
81
82/**
83 * Returns given string safe for display as HTML. Renders entities.
84 *
85 * strip_tags() does not validating HTML syntax or structure, so it might strip whole passages
86 * with broken HTML.
87 *
88 * ### Options:
89 *
90 * - remove (boolean) if true strips all HTML tags before encoding
91 * - charset (string) the charset used to encode the string
92 * - quotes (int) see http://php.net/manual/en/function.htmlentities.php
93 *
94 * @param string $string String from where to strip tags
95 * @param array $options Array of options to use.
96 * @return string Sanitized string
97 * @access public
98 * @static
99 */
100        function html($string, $options = array()) {
101                static $defaultCharset = false;
102                if ($defaultCharset === false) {
103                        $defaultCharset = Configure::read('App.encoding');
104                        if ($defaultCharset === null) {
105                                $defaultCharset = 'UTF-8';
106                        }
107                }
108                $default = array(
109                        'remove' => false,
110                        'charset' => $defaultCharset,
111                        'quotes' => ENT_QUOTES
112                );
113
114                $options = array_merge($default, $options);
115
116                if ($options['remove']) {
117                        $string = strip_tags($string);
118                }
119
120                return htmlentities($string, $options['quotes'], $options['charset']);
121        }
122
123/**
124 * Strips extra whitespace from output
125 *
126 * @param string $str String to sanitize
127 * @return string whitespace sanitized string
128 * @access public
129 * @static
130 */
131        function stripWhitespace($str) {
132                $r = preg_replace('/[\n\r\t]+/', '', $str);
133                return preg_replace('/\s{2,}/u', ' ', $r);
134        }
135
136/**
137 * Strips image tags from output
138 *
139 * @param string $str String to sanitize
140 * @return string Sting with images stripped.
141 * @access public
142 * @static
143 */
144        function stripImages($str) {
145                $str = preg_replace('/(<a[^>]*>)(<img[^>]+alt=")([^"]*)("[^>]*>)(<\/a>)/i', '$1$3$5<br />', $str);
146                $str = preg_replace('/(<img[^>]+alt=")([^"]*)("[^>]*>)/i', '$2<br />', $str);
147                $str = preg_replace('/<img[^>]*>/i', '', $str);
148                return $str;
149        }
150
151/**
152 * Strips scripts and stylesheets from output
153 *
154 * @param string $str String to sanitize
155 * @return string String with <script>, <style>, <link>, <img> elements removed.
156 * @access public
157 * @static
158 */
159        function stripScripts($str) {
160                return preg_replace('/(<link[^>]+rel="[^"]*stylesheet"[^>]*>|<img[^>]*>|style="[^"]*")|<script[^>]*>.*?<\/script>|<style[^>]*>.*?<\/style>|<!--.*?-->/is', '', $str);
161        }
162
163/**
164 * Strips extra whitespace, images, scripts and stylesheets from output
165 *
166 * @param string $str String to sanitize
167 * @return string sanitized string
168 * @access public
169 */
170        function stripAll($str) {
171                $str = Sanitize::stripWhitespace($str);
172                $str = Sanitize::stripImages($str);
173                $str = Sanitize::stripScripts($str);
174                return $str;
175        }
176
177/**
178 * Strips the specified tags from output. First parameter is string from
179 * where to remove tags. All subsequent parameters are tags.
180 *
181 * Ex.`$clean = Sanitize::stripTags($dirty, 'b', 'p', 'div');`
182 *
183 * Will remove all `<b>`, `<p>`, and `<div>` tags from the $dirty string.
184 *
185 * @param string $str String to sanitize
186 * @param string $tag Tag to remove (add more parameters as needed)
187 * @return string sanitized String
188 * @access public
189 * @static
190 */
191        function stripTags() {
192                $params = params(func_get_args());
193                $str = $params[0];
194
195                for ($i = 1, $count = count($params); $i < $count; $i++) {
196                        $str = preg_replace('/<' . $params[$i] . '\b[^>]*>/i', '', $str);
197                        $str = preg_replace('/<\/' . $params[$i] . '[^>]*>/i', '', $str);
198                }
199                return $str;
200        }
201
202/**
203 * Sanitizes given array or value for safe input. Use the options to specify
204 * the connection to use, and what filters should be applied (with a boolean
205 * value). Valid filters:
206 *
207 * - odd_spaces - removes any non space whitespace characters
208 * - encode - Encode any html entities. Encode must be true for the `remove_html` to work.
209 * - dollar - Escape `$` with `\$`
210 * - carriage - Remove `\r`
211 * - unicode -
212 * - escape - Should the string be SQL escaped.
213 * - backslash -
214 * - remove_html - Strip HTML with strip_tags. `encode` must be true for this option to work.
215 *
216 * @param mixed $data Data to sanitize
217 * @param mixed $options If string, DB connection being used, otherwise set of options
218 * @return mixed Sanitized data
219 * @access public
220 * @static
221 */
222        function clean($data, $options = array()) {
223                if (empty($data)) {
224                        return $data;
225                }
226
227                if (is_string($options)) {
228                        $options = array('connection' => $options);
229                } else if (!is_array($options)) {
230                        $options = array();
231                }
232
233                $options = array_merge(array(
234                        'connection' => 'default',
235                        'odd_spaces' => true,
236                        'remove_html' => false,
237                        'encode' => true,
238                        'dollar' => true,
239                        'carriage' => true,
240                        'unicode' => true,
241                        'escape' => true,
242                        'backslash' => true
243                ), $options);
244
245                if (is_array($data)) {
246                        foreach ($data as $key => $val) {
247                                $data[$key] = Sanitize::clean($val, $options);
248                        }
249                        return $data;
250                } else {
251                        if ($options['odd_spaces']) {
252                                $data = str_replace(chr(0xCA), '', $data);
253                        }
254                        if ($options['encode']) {
255                                $data = Sanitize::html($data, array('remove' => $options['remove_html']));
256                        }
257                        if ($options['dollar']) {
258                                $data = str_replace("\\\$", "$", $data);
259                        }
260                        if ($options['carriage']) {
261                                $data = str_replace("\r", "", $data);
262                        }
263                        if ($options['unicode']) {
264                                $data = preg_replace("/&amp;#([0-9]+);/s", "&#\\1;", $data);
265                        }
266                        if ($options['escape']) {
267                                $data = Sanitize::escape($data, $options['connection']);
268                        }
269                        if ($options['backslash']) {
270                                $data = preg_replace("/\\\(?!&amp;#|\?#)/", "\\", $data);
271                        }
272                        return $data;
273                }
274        }
275
276/**
277 * Formats column data from definition in DBO's $columns array
278 *
279 * @param Model $model The model containing the data to be formatted
280 * @access public
281 * @static
282 */
283        function formatColumns(&$model) {
284                foreach ($model->data as $name => $values) {
285                        if ($name == $model->alias) {
286                                $curModel =& $model;
287                        } elseif (isset($model->{$name}) && is_object($model->{$name}) && is_subclass_of($model->{$name}, 'Model')) {
288                                $curModel =& $model->{$name};
289                        } else {
290                                $curModel = null;
291                        }
292
293                        if ($curModel != null) {
294                                foreach ($values as $column => $data) {
295                                        $colType = $curModel->getColumnType($column);
296
297                                        if ($colType != null) {
298                                                $db =& ConnectionManager::getDataSource($curModel->useDbConfig);
299                                                $colData = $db->columns[$colType];
300
301                                                if (isset($colData['limit']) && strlen(strval($data)) > $colData['limit']) {
302                                                        $data = substr(strval($data), 0, $colData['limit']);
303                                                }
304
305                                                if (isset($colData['formatter']) || isset($colData['format'])) {
306
307                                                        switch (strtolower($colData['formatter'])) {
308                                                                case 'date':
309                                                                        $data = date($colData['format'], strtotime($data));
310                                                                break;
311                                                                case 'sprintf':
312                                                                        $data = sprintf($colData['format'], $data);
313                                                                break;
314                                                                case 'intval':
315                                                                        $data = intval($data);
316                                                                break;
317                                                                case 'floatval':
318                                                                        $data = floatval($data);
319                                                                break;
320                                                        }
321                                                }
322                                                $model->data[$name][$column]=$data;
323                                                /*
324                                                switch ($colType) {
325                                                        case 'integer':
326                                                        case 'int':
327                                                                return  $data;
328                                                        break;
329                                                        case 'string':
330                                                        case 'text':
331                                                        case 'binary':
332                                                        case 'date':
333                                                        case 'time':
334                                                        case 'datetime':
335                                                        case 'timestamp':
336                                                        case 'date':
337                                                                return "'" . $data . "'";
338                                                        break;
339                                                }
340                                                */
341                                        }
342                                }
343                        }
344                }
345        }
346}
Note: See TracBrowser for help on using the repository browser.