1: <?php
2: /* SVN FILE: $Id$ */
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-2012, 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-2012, 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: * @version $Revision$
22: * @modifiedby $LastChangedBy$
23: * @lastmodified $Date$
24: * @license http://www.opensource.org/licenses/mit-license.php The MIT License
25: */
26: /**
27: * Data Sanitization.
28: *
29: * Removal of alpahnumeric characters, SQL-safe slash-added strings, HTML-friendly strings,
30: * and all of the above on arrays.
31: *
32: * @package cake
33: * @subpackage cake.cake.libs
34: */
35: class Sanitize {
36: /**
37: * Removes any non-alphanumeric characters.
38: *
39: * @param string $string String to sanitize
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: * Makes a string SQL-safe.
64: *
65: * @param string $string String to sanitize
66: * @param string $connection Database connection being used
67: * @return string SQL safe string
68: * @access public
69: * @static
70: */
71: function escape($string, $connection = 'default') {
72: $db =& ConnectionManager::getDataSource($connection);
73: if (is_numeric($string) || $string === null || is_bool($string)) {
74: return $string;
75: }
76: $string = substr($db->value($string), 1);
77: $string = substr($string, 0, -1);
78: return $string;
79: }
80: /**
81: * Returns given string safe for display as HTML. Renders entities.
82: *
83: * @param string $string String from where to strip tags
84: * @param boolean $remove If true, the string is stripped of all HTML tags
85: * @return string Sanitized string
86: * @access public
87: * @static
88: */
89: function html($string, $remove = false) {
90: if ($remove) {
91: $string = strip_tags($string);
92: } else {
93: $patterns = array("/\&/", "/%/", "/</", "/>/", '/"/', "/'/", "/\(/", "/\)/", "/\+/", "/-/");
94: $replacements = array("&", "%", "<", ">", """, "'", "(", ")", "+", "-");
95: $string = preg_replace($patterns, $replacements, $string);
96: }
97: return $string;
98: }
99: /**
100: * Strips extra whitespace from output
101: *
102: * @param string $str String to sanitize
103: * @return string whitespace sanitized string
104: * @access public
105: * @static
106: */
107: function stripWhitespace($str) {
108: $r = preg_replace('/[\n\r\t]+/', '', $str);
109: return preg_replace('/\s{2,}/', ' ', $r);
110: }
111: /**
112: * Strips image tags from output
113: *
114: * @param string $str String to sanitize
115: * @return string Sting with images stripped.
116: * @access public
117: * @static
118: */
119: function stripImages($str) {
120: $str = preg_replace('/(<a[^>]*>)(<img[^>]+alt=")([^"]*)("[^>]*>)(<\/a>)/i', '$1$3$5<br />', $str);
121: $str = preg_replace('/(<img[^>]+alt=")([^"]*)("[^>]*>)/i', '$2<br />', $str);
122: $str = preg_replace('/<img[^>]*>/i', '', $str);
123: return $str;
124: }
125: /**
126: * Strips scripts and stylesheets from output
127: *
128: * @param string $str String to sanitize
129: * @return string String with <script>, <style>, <link> elements removed.
130: * @access public
131: * @static
132: */
133: function stripScripts($str) {
134: return preg_replace('/(<link[^>]+rel="[^"]*stylesheet"[^>]*>|<img[^>]*>|style="[^"]*")|<script[^>]*>.*?<\/script>|<style[^>]*>.*?<\/style>|<!--.*?-->/is', '', $str);
135: }
136: /**
137: * Strips extra whitespace, images, scripts and stylesheets from output
138: *
139: * @param string $str String to sanitize
140: * @return string sanitized string
141: * @access public
142: */
143: function stripAll($str) {
144: $str = Sanitize::stripWhitespace($str);
145: $str = Sanitize::stripImages($str);
146: $str = Sanitize::stripScripts($str);
147: return $str;
148: }
149: /**
150: * Strips the specified tags from output. First parameter is string from
151: * where to remove tags. All subsequent parameters are tags.
152: *
153: * @param string $str String to sanitize
154: * @param string $tag Tag to remove (add more parameters as needed)
155: * @return string sanitized String
156: * @access public
157: * @static
158: */
159: function stripTags() {
160: $params = params(func_get_args());
161: $str = $params[0];
162:
163: for ($i = 1, $count = count($params); $i < $count; $i++) {
164: $str = preg_replace('/<' . $params[$i] . '\b[^>]*>/i', '', $str);
165: $str = preg_replace('/<\/' . $params[$i] . '[^>]*>/i', '', $str);
166: }
167: return $str;
168: }
169: /**
170: * Sanitizes given array or value for safe input. Use the options to specify
171: * the connection to use, and what filters should be applied (with a boolean
172: * value). Valid filters: odd_spaces, encode, dollar, carriage, unicode,
173: * escape, backslash.
174: *
175: * @param mixed $data Data to sanitize
176: * @param mixed $options If string, DB connection being used, otherwise set of options
177: * @return mixed Sanitized data
178: * @access public
179: * @static
180: */
181: function clean($data, $options = array()) {
182: if (empty($data)) {
183: return $data;
184: }
185:
186: if (is_string($options)) {
187: $options = array('connection' => $options);
188: } else if (!is_array($options)) {
189: $options = array();
190: }
191:
192: $options = array_merge(array(
193: 'connection' => 'default',
194: 'odd_spaces' => true,
195: 'encode' => true,
196: 'dollar' => true,
197: 'carriage' => true,
198: 'unicode' => true,
199: 'escape' => true,
200: 'backslash' => true
201: ), $options);
202:
203: if (is_array($data)) {
204: foreach ($data as $key => $val) {
205: $data[$key] = Sanitize::clean($val, $options);
206: }
207: return $data;
208: } else {
209: if ($options['odd_spaces']) {
210: $data = str_replace(chr(0xCA), '', str_replace(' ', ' ', $data));
211: }
212: if ($options['encode']) {
213: $data = Sanitize::html($data);
214: }
215: if ($options['dollar']) {
216: $data = str_replace("\\\$", "$", $data);
217: }
218: if ($options['carriage']) {
219: $data = str_replace("\r", "", $data);
220: }
221:
222: $data = str_replace("'", "'", str_replace("!", "!", $data));
223:
224: if ($options['unicode']) {
225: $data = preg_replace("/&#([0-9]+);/s", "&#\\1;", $data);
226: }
227: if ($options['escape']) {
228: $data = Sanitize::escape($data, $options['connection']);
229: }
230: if ($options['backslash']) {
231: $data = preg_replace("/\\\(?!&#|\?#)/", "\\", $data);
232: }
233: return $data;
234: }
235: }
236: /**
237: * Formats column data from definition in DBO's $columns array
238: *
239: * @param Model $model The model containing the data to be formatted
240: * @access public
241: * @static
242: */
243: function formatColumns(&$model) {
244: foreach ($model->data as $name => $values) {
245: if ($name == $model->alias) {
246: $curModel =& $model;
247: } elseif (isset($model->{$name}) && is_object($model->{$name}) && is_subclass_of($model->{$name}, 'Model')) {
248: $curModel =& $model->{$name};
249: } else {
250: $curModel = null;
251: }
252:
253: if ($curModel != null) {
254: foreach ($values as $column => $data) {
255: $colType = $curModel->getColumnType($column);
256:
257: if ($colType != null) {
258: $db =& ConnectionManager::getDataSource($curModel->useDbConfig);
259: $colData = $db->columns[$colType];
260:
261: if (isset($colData['limit']) && strlen(strval($data)) > $colData['limit']) {
262: $data = substr(strval($data), 0, $colData['limit']);
263: }
264:
265: if (isset($colData['formatter']) || isset($colData['format'])) {
266:
267: switch (strtolower($colData['formatter'])) {
268: case 'date':
269: $data = date($colData['format'], strtotime($data));
270: break;
271: case 'sprintf':
272: $data = sprintf($colData['format'], $data);
273: break;
274: case 'intval':
275: $data = intval($data);
276: break;
277: case 'floatval':
278: $data = floatval($data);
279: break;
280: }
281: }
282: $model->data[$name][$column]=$data;
283: /*
284: switch ($colType) {
285: case 'integer':
286: case 'int':
287: return $data;
288: break;
289: case 'string':
290: case 'text':
291: case 'binary':
292: case 'date':
293: case 'time':
294: case 'datetime':
295: case 'timestamp':
296: case 'date':
297: return "'" . $data . "'";
298: break;
299: }
300: */
301: }
302: }
303: }
304: }
305: }
306: }
307: ?>