Sources for file plugins/class/filter.php in version 4.0 Beta 1
Click on a comment to hide it. Click here to show all comments.
/**
* Project: Xnyo 4: Bubbles
* File: plugins/class/filter.php
*
* Version: 4.0-dev
* SVN Id: $Id: filter.php 5 2007-05-18 03:49:07Z bok $
* SVN URL: $HeadURL:
http://svn.syd.wholesalebroadband.com.au/xnyo/trunk/plugins/class/filter.php $
* Authors: Robert Amos <bok[at]odynia.org>
*
* Copyright (c) 2001-2007 Robert Amos <bok[at]odynia.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
**/
/**
* This is the variable filter. This filters ALL forms of input from the user.
* MAKE SURE YOU USE IT!
**/
class XnyoFilter implements XnyoClassPlugin
{
// Plugin Information
public $_plugin_info = array
(
'name' => 'Xnyo Filter Plugin',
'description' => 'Filters incoming information from the user.',
'action' => XNYO_PLUGIN_ACTION_STORAGE,
'varname' => 'filter'
);
/**
* Information Storage
**/
private $get;
private $post;
private $cookie;
private $env;
private $server;
private $files;
private $silent;
private $types;
private $xnyo;
/**
* Constructor
**/
public function __construct ()
{
$this->xnyo = $GLOBALS['xnyo_parent'];
// valid types
$this->types = get_class_methods('XnyoInput');
/**
* Remove all content from the superglobals
**/
if (XNYO_DEBUG) $this->xnyo->d('Copying Superglobals to private storage arrays.');
$this->get = $_GET;
$this->post = $_POST;
$this->cookie = $_COOKIE;
$this->env = $_ENV;
$this->server = $_SERVER;
$this->files = $_FILES;
if (XNYO_DEBUG) $this->xnyo->d('Variable Count: $_GET(<b>%d</b>), $_POST(<b>%d</b>),
$_COOKIES(<b>%d</b>), $_ENV(<b>%d</b>), $_SERVER(<b>%d</b>), $_FILES(<b>%d</b>)', count($this->get),
count($this->post), count($this->cookie), count($this->env), count($this->server),
count($this->files));
/**
* We're now safe! Empty the superglobals
**/
if (XNYO_DEBUG) $this->xnyo->d('Emptying Superglobals.');
$_GET = $_POST = $_COOKIE = $_ENV = $_SERVER = $_FILES = $_REQUEST = array();
/**
* Filter the known server variables
**/
if (XNYO_DEBUG) $this->xnyo->d('Filtering Known $_SERVER[] elements.');
$this->filter_known_server_vars();
}
/**
* Filter a variable
**/
public function __call ($func, $args)
{
// function determination
$r = strtolower(ini_get('variables_order'));
$req = false;
if ($func == 'fget')
{
$sup = &$_GET; $n = '_GET'; $obj = 'get';
if (strpos($r, 'g') !== FALSE) $req = true;
} elseif ($func == 'fpost')
{
$sup = &$_POST; $n = '_POST'; $obj = 'post';
if (strpos($r, 'p') !== FALSE) $req = true;
} elseif ($func == 'fcookie')
{
$sup = &$_COOKIE; $n = '_COOKIE'; $obj = 'cookie';
if (strpos($r, 'c') !== FALSE) $req = true;
} elseif ($func == 'fenv')
{
$sup = &$_ENV; $n = '_ENV'; $obj = 'env';
if (strpos($r, 'e') !== FALSE) $req = true;
} elseif ($func == 'fserver')
{
$sup = &$_SERVER; $n = '_SERVER'; $obj = 'server';
if (strpos($r, 's') !== FALSE) $req = true;
} elseif ($func == 'ffile')
{
$sup = &$_FILES; $n = '_FILES'; $obj = 'files';
} else
{
throw new XnyoError('Undefined function <b>XnyoFilter::%s</b>', $func);
}
// defaults
if (empty($args[0])) throw new XnyoError('Empty $name specified when filtering $%s variable.',
$n);
else $name = $args[0];
if (!isset($args[1]) || is_null($args[1])) $type = 'text';
else $type = $args[1];
// handle unset variables, no need going any further
if (!isset($this->{$obj}[$name]))
{
if (XNYO_DEBUG && !$this->silent) $this->xnyo->d('Filtering $%s variable <b>%s</b> as <b>%s</b>,
but variable not set.', $n, $name, $type);
return false;
}
// return it to the superglobal
$sup[$name] = $this->filter($this->{$obj}[$name], $type);
// has the variable been modified from its existing state?
$mod = false;
if (is_array($sup[$name]))
{
$this->xnyo->filter->{$obj}[$name] = array();
foreach ($sup[$name] as $k => $v)
{
if ($k == '')
continue;
$this->xnyo->filter->{$obj}[$name][$k] = ($v != $this->{$obj}[$name][$k]);
if ($this->xnyo->filter->{$obj}[$name][$k] == true)
$mod = true;
}
} else
{
$this->xnyo->filter->{$obj}[$name] = ($sup[$name] != $this->{$obj}[$name]);
if ($this->xnyo->filter->{$obj}[$name] == true)
$mod = true;
}
// debug
if (XNYO_DEBUG && !$this->silent)
{
if (is_array($type))
$this->xnyo->d('Filtered $%s variable <b>%s</b> as array(<b>%s</b>), it was <b>%s</b>.', $n,
$name, $type[0], $mod ? 'modified' : 'not modified');
elseif ($type{0} == '/')
$this->xnyo->d('Filtered $%s variable <b>%s</b> using regexp <b>%s</b>, it was <b>%s</b>.', $n,
$name, $type, $mod ? 'modified' : 'not modified');
else
$this->xnyo->d('Filtered $%s variable <b>%s</b> as <b>%s</b>, it was <b>%s</b>.', $n, $name,
$type, $mod ? 'modified' : 'not modified');
}
// return it to the $_REQUEST array
if ($req && empty($_REQUEST[$name]))
$_REQUEST[$name] = $sup[$name];
// and make it global, if thats what they want
if ($this->xnyo->filter->globals && !isset($GLOBALS[$name]))
{
if (XNYO_DEBUG && !$this->silent) $this->xnyo->d('Adding $%s variable <b>$%s</b> to the global
scope.', $n, $name);
$GLOBALS[$name] = $sup[$name];
}
}
/**
* Perform filtering on a variable
**/
private function filter ($data, $type)
{
// deal with arrays
if (is_array($type))
{
$at = $type[0];
$type = '_array';
// deal with regexps
} elseif ($type{0} == '/')
{
$pat = $type;
$type = 'regexp';
}
// run it through the appropriate input function
if (!in_array($type, $this->types))
throw new XnyoError('Attempted to filter data using <b>XnyoInput::%s()</b>, but input method not
found.', $type);
// do it!
if (isset($at))
$r = XnyoInput::$type($data, $at);
elseif ($type == 'regexp')
$r = XnyoInput::$type($data, $pat);
else
$r = XnyoInput::$type($data);
// filtered
return $r;
}
/**
* Pass-through a server variable
**/
private function passthru ($varname)
{
if (isset($this->server[$varname]))
$_SERVER[$varname] = $this->server[$varname];
}
/**
* Filter known $_SERVER variables
**/
public function filter_known_server_vars ()
{
// no debug messages, there are too many
$this->silent = true;
// PHP_SELF, be very careful with this one! Since its most often used to
// pass requests back to the server, we urlencode this one
$this->fserver('PHP_SELF', 'htmlsafe');
// $argv && $argc
$this->fserver('argv', array('htmlsafe'));
$this->fserver('argc', 'int');
// QUERY_STRING - another one of those potentially harmful ones. hmm!
$this->fserver('QUERY_STRING', 'htmlsafe');
// HTTP_* headers
$this->fserver('HTTP_ACCEPT', 'header');
$this->fserver('HTTP_ACCEPT_CHARSET', 'header');
$this->fserver('HTTP_ACCEPT_ENCODING', 'header');
$this->fserver('HTTP_ACCEPT_LANGUAGE', 'header');
$this->fserver('HTTP_CONNECTION', 'header');
$this->fserver('HTTP_HOST', 'host');
$this->fserver('HTTP_REFERER', 'htmlsafe');
$this->fserver('HTTP_USER_AGENT', 'header');
// REQUEST_URI
$this->fserver('REQUEST_URI', 'htmlsafe');
/**
* Server assigned variables
*
* These variables are all generated by the server and are not
* controllable/changeable by the user. This saves about 5ms per
* call.
*
* If you disagree with this assessment, drop us a line and we'll
* filter the requested element!
**/
// GATEWAY_INTERFACE should be CGI/revision.number
//$this->fserver('GATEWAY_INTERFACE', '/[^CGI\/0-9.]/i');
$this->passthru('GATEWAY_INTERFACE');
// SERVER_ADDR, an IP Address
//$this->fserver('SERVER_ADDR', 'ip');
$this->passthru('SERVER_ADDR');
// SERVER_NAME, the hostname
//$this->fserver('SERVER_NAME', 'host');
$this->passthru('SERVER_NAME');
// SERVER_SOFTWARE
//$this->fserver('SERVER_SOFTWARE');
$this->passthru('SERVER_SOFTWARE');
// SERVER_PROTOCOL
//$this->fserver('SERVER_PROTOCOL', '/[^A-Z\/0-9.]/');
$this->passthru('SERVER_PROTOCOL');
// REQUEST_METHOD
//$this->fserver('REQUEST_METHOD', 'uppercase');
$this->passthru('REQUEST_METHOD');
// REQUEST_TIME
//$this->fserver('REQUEST_TIME', 'int');
$this->passthru('REQUEST_TIME');
// DOCUMENT_ROOT - prepend the leading / again
//$this->fserver('DOCUMENT_ROOT', 'abs_filename');
$this->passthru('DOCUMENT_ROOT');
// HTTPS
//$this->fserver('HTTPS');
$this->passthru('HTTPS');
// REMOTE_ADDR/HOST/PORT
//$this->fserver('REMOTE_ADDR', 'ip');
$this->passthru('REMOTE_ADDR');
//$this->fserver('REMOTE_HOST', 'host');
$this->passthru('REMOTE_HOST');
//$this->fserver('REMOTE_PORT', 'int');
$this->passthru('REMOTE_PORT');
// SCRIPT_FILENAME
//$this->fserver('SCRIPT_FILENAME', 'abs_filename');
$this->passthru('SCRIPT_FILENAME');
// SERVER_ADMIN
//$this->fserver('SERVER_ADMIN');
$this->passthru('SERVER_ADMIN');
// SERVER details
//$this->fserver('SERVER_PORT', 'int');
$this->passthru('SERVER_PORT');
//$this->fserver('SERVER_SIGNATURE', 'header');
$this->passthru('SERVER_SIGNATURE');
// PATH_TRANSLATED
//$this->fserver('PATH_TRANSLATED');
$this->passthru('PATH_TRANSLATED');
// SCRIPT_NAME
//$this->fserver('SCRIPT_NAME', 'abs_filename');
$this->passthru('SCRIPT_NAME');
// authentication
//$this->fserver('PHP_AUTH_DIGEST');
$this->passthru('PHP_AUTH_DIGEST');
//$this->fserver('PHP_AUTH_USER', 'username');
$this->passthru('PHP_AUTH_USER');
//$this->fserver('PHP_AUTH_PW', 'password');
$this->passthru('PHP_AUTH_PW');
//$this->fserver('AUTH_TYPE', 'safetext');
$this->passthru('AUTH_TYPE');
// turn em back on
$this->silent = false;
}
/**
* Get Valid input types
**/
public function get_valid_types ()
{
return $this->types;
}
}
