sanitize.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: sanitize_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * Washes strings from unwanted noise.
00005  *
00006  * Helpful methods to make unsafe strings usable.
00007  *
00008  * PHP versions 4 and 5
00009  *
00010  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00011  * Copyright 2005-2008, Cake Software Foundation, Inc.
00012  *                              1785 E. Sahara Avenue, Suite 490-204
00013  *                              Las Vegas, Nevada 89104
00014  *
00015  * Licensed under The MIT License
00016  * Redistributions of files must retain the above copyright notice.
00017  *
00018  * @filesource
00019  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00020  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00021  * @package         cake
00022  * @subpackage      cake.cake.libs
00023  * @since           CakePHP(tm) v 0.10.0.1076
00024  * @version         $Revision: 580 $
00025  * @modifiedby      $LastChangedBy: gwoo $
00026  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00027  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00028  */
00029 /**
00030  * Data Sanitization.
00031  *
00032  * Removal of alpahnumeric characters, SQL-safe slash-added strings, HTML-friendly strings,
00033  * and all of the above on arrays.
00034  *
00035  * @package     cake
00036  * @subpackage  cake.cake.libs
00037  */
00038 class Sanitize {
00039 /**
00040  * Removes any non-alphanumeric characters.
00041  *
00042  * @param string $string String to sanitize
00043  * @return string Sanitized string
00044  * @access public
00045  * @static
00046  */
00047     function paranoid($string, $allowed = array()) {
00048         $allow = null;
00049         if (!empty($allowed)) {
00050             foreach ($allowed as $value) {
00051                 $allow .= "\\$value";
00052             }
00053         }
00054 
00055         if (is_array($string)) {
00056             $cleaned = array();
00057             foreach ($string as $key => $clean) {
00058                 $cleaned[$key] = preg_replace("/[^{$allow}a-zA-Z0-9]/", '', $clean);
00059             }
00060         } else {
00061             $cleaned = preg_replace("/[^{$allow}a-zA-Z0-9]/", '', $string);
00062         }
00063         return $cleaned;
00064     }
00065 /**
00066  * Makes a string SQL-safe.
00067  *
00068  * @param string $string String to sanitize
00069  * @param string $connection Database connection being used
00070  * @return string SQL safe string
00071  * @access public
00072  * @static
00073  */
00074     function escape($string, $connection = 'default') {
00075         $db =& ConnectionManager::getDataSource($connection);
00076         if (is_numeric($string)  || $string === null) {
00077             return $string;
00078         }
00079         $string = substr($db->value($string), 1);
00080         $string = substr($string, 0, -1);
00081         return $string;
00082     }
00083 /**
00084  * Returns given string safe for display as HTML. Renders entities.
00085  *
00086  * @param string $string String from where to strip tags
00087  * @param boolean $remove If true, the string is stripped of all HTML tags
00088  * @return string Sanitized string
00089  * @access public
00090  * @static
00091  */
00092     function html($string, $remove = false) {
00093         if ($remove) {
00094             $string = strip_tags($string);
00095         } else {
00096             $patterns = array("/\&/", "/%/", "/</", "/>/", '/"/', "/'/", "/\(/", "/\)/", "/\+/", "/-/");
00097             $replacements = array("&amp;", "&#37;", "&lt;", "&gt;", "&quot;", "&#39;", "&#40;", "&#41;", "&#43;", "&#45;");
00098             $string = preg_replace($patterns, $replacements, $string);
00099         }
00100         return $string;
00101     }
00102 /**
00103  * Strips extra whitespace from output
00104  *
00105  * @param string $str String to sanitize
00106  * @access public
00107  * @static
00108  */
00109     function stripWhitespace($str) {
00110         $r = preg_replace('/[\n\r\t]+/', '', $str);
00111         return preg_replace('/\s{2,}/', ' ', $r);
00112     }
00113 /**
00114  * Strips image tags from output
00115  *
00116  * @param string $str String to sanitize
00117  * @access public
00118  * @static
00119  */
00120     function stripImages($str) {
00121         $str = preg_replace('/(<a[^>]*>)(<img[^>]+alt=")([^"]*)("[^>]*>)(<\/a>)/i', '$1$3$5<br />', $str);
00122         $str = preg_replace('/(<img[^>]+alt=")([^"]*)("[^>]*>)/i', '$2<br />', $str);
00123         $str = preg_replace('/<img[^>]*>/i', '', $str);
00124         return $str;
00125     }
00126 /**
00127  * Strips scripts and stylesheets from output
00128  *
00129  * @param string $str String to sanitize
00130  * @access public
00131  * @static
00132  */
00133     function stripScripts($str) {
00134         return preg_replace('/(<link[^>]+rel="[^"]*stylesheet"[^>]*>|<img[^>]*>|style="[^"]*")|<script[^>]*>.*?<\/script>|<style[^>]*>.*?<\/style>|<!--.*?-->/i', '', $str);
00135     }
00136 /**
00137  * Strips extra whitespace, images, scripts and stylesheets from output
00138  *
00139  * @param string $str String to sanitize
00140  * @access public
00141  */
00142     function stripAll($str) {
00143         $str = Sanitize::stripWhitespace($str);
00144         $str = Sanitize::stripImages($str);
00145         $str = Sanitize::stripScripts($str);
00146         return $str;
00147     }
00148 /**
00149  * Strips the specified tags from output. First parameter is string from
00150  * where to remove tags. All subsequent parameters are tags.
00151  *
00152  * @param string $str String to sanitize
00153  * @param string $tag Tag to remove (add more parameters as needed)
00154  * @access public
00155  * @static
00156  */
00157     function stripTags() {
00158         $params = params(func_get_args());
00159         $str = $params[0];
00160 
00161         for ($i = 1; $i < count($params); $i++) {
00162             $str = preg_replace('/<' . $params[$i] . '[^>]*>/i', '', $str);
00163             $str = preg_replace('/<\/' . $params[$i] . '[^>]*>/i', '', $str);
00164         }
00165         return $str;
00166     }
00167 /**
00168  * Sanitizes given array or value for safe input. Use the options to specify
00169  * the connection to use, and what filters should be applied (with a boolean
00170  * value). Valid filters: odd_spaces, encode, dollar, carriage, unicode,
00171  * escape, backslash.
00172  *
00173  * @param mixed $data Data to sanitize
00174  * @param mixed $options If string, DB connection being used, otherwise set of options
00175  * @return mixed Sanitized data
00176  * @access public
00177  * @static
00178  */
00179     function clean($data, $options = array()) {
00180         if (empty($data)) {
00181             return $data;
00182         }
00183 
00184         if (is_string($options)) {
00185             $options = array('connection' => $options);
00186         } else if (!is_array($options)) {
00187             $options = array();
00188         }
00189 
00190         $options = array_merge(array(
00191             'connection' => 'default',
00192             'odd_spaces' => true,
00193             'encode' => true,
00194             'dollar' => true,
00195             'carriage' => true,
00196             'unicode' => true,
00197             'escape' => true,
00198             'backslash' => true
00199         ), $options);
00200 
00201         if (is_array($data)) {
00202             foreach ($data as $key => $val) {
00203                 $data[$key] = Sanitize::clean($val, $options);
00204             }
00205             return $data;
00206         } else {
00207             if ($options['odd_spaces']) {
00208                 $data = str_replace(chr(0xCA), '', str_replace(' ', ' ', $data));
00209             }
00210             if ($options['encode']) {
00211                 $data = Sanitize::html($data);
00212             }
00213             if ($options['dollar']) {
00214                 $data = str_replace("\\\$", "$", $data);
00215             }
00216             if ($options['carriage']) {
00217                 $data = str_replace("\r", "", $data);
00218             }
00219 
00220             $data = str_replace("'", "'", str_replace("!", "!", $data));
00221 
00222             if ($options['unicode']) {
00223                 $data = preg_replace("/&amp;#([0-9]+);/s", "&#\\1;", $data);
00224             }
00225             if ($options['escape']) {
00226                 $data = Sanitize::escape($data, $options['connection']);
00227             }
00228             if ($options['backslash']) {
00229                 $data = preg_replace("/\\\(?!&amp;#|\?#)/", "\\", $data);
00230             }
00231             return $data;
00232         }
00233     }
00234 /**
00235  * Formats column data from definition in DBO's $columns array
00236  *
00237  * @param Model $model The model containing the data to be formatted
00238  * @access public
00239  * @static
00240  */
00241     function formatColumns(&$model) {
00242         foreach ($model->data as $name => $values) {
00243             if ($name == $model->name) {
00244                 $curModel =& $model;
00245             } elseif (isset($model->{$name}) && is_object($model->{$name}) && is_subclass_of($model->{$name}, 'Model')) {
00246                 $curModel =& $model->{$name};
00247             } else {
00248                 $curModel = null;
00249             }
00250 
00251             if ($curModel != null) {
00252                 foreach ($values as $column => $data) {
00253                     $colType = $curModel->getColumnType($column);
00254 
00255                     if ($colType != null) {
00256                         $db =& ConnectionManager::getDataSource($curModel->useDbConfig);
00257                         $colData = $db->columns[$colType];
00258 
00259                         if (isset($colData['limit']) && strlen(strval($data)) > $colData['limit']) {
00260                             $data = substr(strval($data), 0, $colData['limit']);
00261                         }
00262 
00263                         if (isset($colData['formatter']) || isset($colData['format'])) {
00264 
00265                             switch(strtolower($colData['formatter'])) {
00266                                 case 'date':
00267                                     $data = date($colData['format'], strtotime($data));
00268                                 break;
00269                                 case 'sprintf':
00270                                     $data = sprintf($colData['format'], $data);
00271                                 break;
00272                                 case 'intval':
00273                                     $data = intval($data);
00274                                 break;
00275                                 case 'floatval':
00276                                     $data = floatval($data);
00277                                 break;
00278                             }
00279                         }
00280                         $model->data[$name][$column]=$data;
00281                         /*
00282                         switch($colType) {
00283                             case 'integer':
00284                             case 'int':
00285                                 return  $data;
00286                             break;
00287                             case 'string':
00288                             case 'text':
00289                             case 'binary':
00290                             case 'date':
00291                             case 'time':
00292                             case 'datetime':
00293                             case 'timestamp':
00294                             case 'date':
00295                                 return "'" . $data . "'";
00296                             break;
00297                         }
00298                         */
00299                     }
00300                 }
00301             }
00302         }
00303     }
00304 }
00305 ?>