[geeklog-cvs] Geeklog-2/system Filter.php,NONE,1.1
tony at iowaoutdoors.org
tony at iowaoutdoors.org
Wed Jan 5 17:36:17 EST 2005
Update of /var/cvs/Geeklog-2/system
In directory www:/tmp/cvs-serv13948
Added Files:
Filter.php
Log Message:
Port of Blaine Lang's GL 1.3.x version written in PHP4 over to PHP5. I took liberty to remove reference to global variables and change it to meet the GL2 coding standards.
--- NEW FILE: Filter.php ---
<?php
/* Reminder: always indent with 4 spaces (no tabs). */
/**
* Geeklog 2
*
* License Details To Be Determined
*
*/
/**
* This is a basic filter class that allows for quick and effective filtering of potentially
* harmfull stuff. This includes SQL injection, XSS vulnerabilties and unwanted HTML.
*
* @copyright 2005 Tony Bibbs, Vincent Furia
* @author Blaine Lang
* @author Tony Bibbs <tony at geeklog.net>
*
*/
/**
* Include the base kses class if not already loaded
*/
require_once 'Kses.php';
class Geeklog_Filter extends Geeklog_Kses {
protected $string = '';
protected $permissions = '';
protected $isNumeric = false;
protected $logging = false;
protected $setGlobal = false;
protected $censorData = false;
protected $options;
/**
* Constructor
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param array $options Array of options to this class. Current supported options are:
* 'allowedProtocols' => array()
* 'allowedHTML' => array()
* 'censorMode' => int (const)
* 'censorList' => array(0
* 'censorReplace'=> string
*
*/
public function __construct($options)
{
}
/**
* Filter or sanitize single parm
*/
public function filterparm($parm)
{
global $HTTP_SERVER_VARS;
$p = $this->parse($parm);
if ($this->isNumeric ) {
// Note: PHP's is_numeric() accepts values like 4e4 as numeric
if (!is_numeric($p) OR (preg_match( '/^([0-9]+)$/', $p) == 0)) {
$p = 0;
}
} else {
$p = preg_replace( '/\/\*.*/', '', $p );
$pa = explode( "'", $p );
$pa = explode( '"', $pa[0] );
$pa = explode( '`', $pa[0] );
$pa = explode( ';', $pa[0] );
$pa = explode( '\\', $pa[0] );
$p = $pa[0];
}
/*if ($this->logging) {
if (strcmp($p, $parm) != 0)
{
COM_errorLog( "Filter applied: >> $parm << filtered to $p [IP {$HTTP_SERVER_VARS['REMOTE_ADDR']}]", 1);
}
}*/
return $p;
}
/**
* Prepare data for SQL insert and apply filtering
* Supports passing a single parm or array of parms
*/
public function prepareForDB($data)
{
if (is_array($data)) {
// loop through array and apply the filters
foreach ($data as $var) {
//$return_data[] = addslashes($this->filterHTML($var));
// Removed addslashes() call because Propel/Creole should handle this in GL2
$return_data[] = $this->filterHTML($var);
}
return $return_data;
} else {
$data = $this->filterHTML($data);
//$data = addslashes($data);
// Removed addslashes() call because Propel/Creole should handle this in GL2
return $data;
}
}
public function filterHTML($message)
{
// strip_tags() gets confused by HTML comments ...
$message = preg_replace( '/<!--.+?-->/', '', $message );
if (isset($this->allowedProtocols) AND is_array($this->allowedProtocols)
AND (sizeof($this->allowedProtocols) > 0)) {
$this->protocols($this->allowedProtocols);
} else {
$this->protocols(array('http:','https:','ftp:'));
}
if (empty($this->permissions) OR !SEC_hasRights($this->permissions) OR
empty($this->$adminHTML))
{
$html = $this->userHTML;
} else {
$html = array_merge_recursive($this->userHTML,$this->adminHTML);
}
foreach ($html as $tag => $attr) {
$this->addHTML($tag, $attr);
}
$message = $this->parse( $message );
$message = $this->formatCode($message);
$message = $this->censor($message);
return $message;
}
/**
* Apply filtering to a single parm or array of parms
* Parms may be in either $_POST or $_GET input parms array
* If type (GET or POST) is not set then POST is checked first
* Optionally Parms can be made global
*/
public function sanitizeParms($vars,$type='')
{
$return_data = array();
//setup common reference to SuperGlobals depending which array is needed
if ($type == 'GET' OR $type == 'POST') {
if ($type =='GET') {
$SG_Array =& $_GET;
}
if ($type =='POST') {
$SG_Array =& $_POST;
}
// loop through SuperGlobal data array and grab out data for allowed fields if found
foreach ($vars as $key) {
if (array_key_exists($key,$SG_Array)) {
$return_data[$key]=$SG_Array[$key];
}
}
} else {
foreach ($vars as $key) {
if (array_key_exists($key, $_POST)) {
$return_data[$key] = $_POST[$key];
} elseif (array_key_exists($key, $_GET)) {
$return_data[$key] = $_GET[$key];
}
}
}
// loop through $vars array and apply the filter
foreach ($vars as $value) {
$return_data[$value] = $this->filterparm($return_data[$value]);
}
// Optionally set $GLOBALS or return the array
if ($this->setGlobal) {
// loop through final data and define all the variables using the $GLOBALS array
foreach ($return_data as $key=>$value) {
$GLOBALS[$key]=$value;
}
} else {
return $return_data;
}
}
public function formatCode($message)
{
// Get rid of any newline characters
$message = preg_replace("/\n/", '', $message);
// Replace any $ with $ (HTML equiv)
$message = str_replace('$', '$', $message);
// handle [code] ... [/code]
do {
$start_pos = strpos( strtolower($message), '[code]');
if ($start_pos !== false) {
$end_pos = strpos(strtolower($message), '[/code]');
if ($end_pos !== false) {
$encoded = $this->_handleCode(substr( $message, $start_pos + 6,
$end_pos - ( $start_pos + 6 )));
$encoded = '<pre><code>' . $encoded . '</code></pre>';
$message = substr( $message, 0, $start_pos ) . $encoded
. substr( $message, $end_pos + 7 );
} else {
// missing [/code]
// Treat the rest of the text as code (so as not to lose any
// special characters). However, the calling entity should
// better be checking for missing [/code] before calling this
// function ...
$encoded = $this->handleCode( substr( $message, $start_pos + 6 ));
$encoded = '<pre><code>' . $encoded . '</code></pre>';
$message = substr( $message, 0, $start_pos ) . $encoded;
}
}
}
while ($start_pos !== false);
return $message;
}
/**
* Handles the part within a [code] ... [/code] section, i.e. escapes all
* special characters.
*
* @param string $str the code section to encode
* @return string $str with the special characters encoded
*
*/
private function handleCode($str)
{
$search = array('&', '\\', '<', '>', '[', ']');
$replace = array('&', '\', '<', '>', '[', ']');
$str = str_replace($search, $replace, $str);
return $str;
}
/**
* This censors inappropriate content
*
* This will replace 'bad words' with something more appropriate
*
* @param string $message String to check
* @return string Edited $Message
*
*/
public function censor($message)
{
$editedMessage = $message;
if ($this->censorData) {
if (is_array($this->censorList)) {
$replacement = $this->censorReplace;
switch($this->censorMode)
{
case 1: // Exact match
$regExPrefix = '(\s*)';
$regExSuffix = '(\W*)';
break;
case 2: // Word beginning
$regExPrefix = '(\s*)';
$regExSuffix = '(\w*)';
break;
case 3: // Word fragment
$regExPrefix = '(\w*)';
$regExSuffix = '(\w*)';
break;
}
for ($i = 0; $i < count($this->censorList); $i++ ) {
$editedMessage = eregi_replace($regExPrefix . $this->censorList[$i] .
$regExSuffix, "\\1$replacement\\2", $editedMessage );
}
}
}
return $editedMessage;
}
public function setPermissions($permissions)
{
$this->permissions = $permissions;
}
public function setLogging($state=false)
{
$this->logging = $state;
}
}
?>
More information about the geeklog-cvs
mailing list