[126] | 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 | } |
---|