1 | <?php |
---|
2 | App::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 | */ |
---|
33 | class 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("/&#([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("/\\\(?!&#|\?#)/", "\\", $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 | } |
---|