Thanx for the advice on print, but I'll stick with print_r(), as I understand it, I know how to use it and I can read it, and only I need to ultimately read it (but I'll remember to pretty it up for others when it's necessary).. but please, this argument is a total tangent from the problem at hand..
analyze() method is the main method used by the DataAnalyzer class constructor. $POST is put into array_scan() via analyze within a dynamic field loop, $array contains either everything in $POST, $GET, $COOKIE or, for that matter, anything in $array itself if you have an array variable that you put directly into array_scan() method itself (since in PHP version 4 there is no such thing as "private", "protected", etc.), and scan() method only modifies the data in $this->data which is set via $this->setData() within array_scan() for each element in $array, scanned via scan() and then reset back into $array.
Here is the whole thing:
/**
* Analyze data provided via parameter or via $_GET, $_POST and $_COOKIE that might contain malicious code or SQL injection attempts
*
* @author Phil
* @version 1.2.0
* @package TOOLS
*/
class DataAnalyzer {
/**
* @access private
* @var mixed $data
*/
var $data;
/**
* @access private
* @var boolean $willLog (default true)
*/
var $willLog = true;
/**
* @access private
* @var boolean $hasFoundEmbeddedExec (default false)
*/
var $hasFoundEmbeddedExec = false;
/**
* @access private
* @var boolean $hasFoundEmbeddedExec (default false)
*/
var $hasFoundSQLInjection = false;
/**
* @access private
* @var boolean $hasFoundEmbeddedExec (default false)
*/
var $hasFoundMaliciousScript = false;
/**
* Do note that this LogGenerator object property can only be instantiated if the project inheriting this client class has an available LogGenerator class
*
* @access private
* @var LogGenerator $log
*/
var $log;
/**
* @access private
* @var DBActionPerformer $dbAP
*/
var $dbAP;
/**
* Constructor
*
* @access public
* @var mixed $data (optional)
* @var boolean $willLog (default true)
*/
function DataAnalyzer($data = '', $willLog = true) { // CONSTRUCTOR
global $section, $action;
if ($data) $this->data = $data;
if ($willLog !== true) $this->willLog = $willLog;
if ($this->willLog && class_exists('LogGenerator')) $this->log =& new LogGenerator($section, $action);
if (class_exists('DBActionPerformer') && @!is_a($this, 'DBActionPerformer')) $this->dbAP =& new DBActionPerformer();
if (class_exists('DBActionPerformer') && @is_a($this, 'DBActionPerformer')) $this->dbAP =& $this; // TO ENSURE PROPER FUNCTIONALITY WITHIN scan()
if ($this->data) return $this->analyze(); else $this->analyze();
}
//----------------------------------------------------------------- --* GETTER/SETTER METHODS *-- ------------------------------------------------------------------------------------------------------
/**
* Retrive $this->data
*
* @access private
* @return mixed $this->data
*/
function &getData() { // STATIC STRING METHOD
return $this->data;
}
/**
* Set $this->data
*
* @access private
* @param mixed $data
*/
function &setData($data) { // STATIC VOID METHOD
$this->data = $data;
}
//------------------------------------------------------------- --* END OF GETTER/SETTER METHODS *-- -------------------------------------------------------------------------------------------------
/**
* Internal method that will auto-execute via constructor.
*
* Purge any data containing any potentially harmful patterns such as <!.. !> auto-executable script, along with <script>, <embed> and <object> HTML codes that could contain
* browser-based auto-launching viral sequences. Also remove potential SQL injection '; that could be added to $_POST form data via user
*
* *Note* This method will also purge all HTML upon global variable $willStripHTML
*
* @access private
* @return mixed $this->data
*/
function &analyze() { // STATIC STRING METHOD
if ($this->data) {
$this->scan();
return $this->getData();
}
foreach (array('get', 'post', 'cookie') as $field) {
global ${'_' . strtoupper($field)}; // IS NOT THE AUTOGLOBAL COLLECTION OBJECT YET SINCE IT IS A DYNAMIC FIELD UNTIL global
if (is_array(${'_' . strtoupper($field)}) && @sizeof(${'_' . strtoupper($field)}) > 0)
${'_' . strtoupper($field)} =& $this->array_scan(${'_' . strtoupper($field)}, '_' . strtoupper($field));
$GLOBALS['_' . strtoupper($field)] = ${'_' . strtoupper($field)}; // JUST IN CASE
if (!$this->dbAP->isSuccessful) return false; // STOP PROCESSING SINCE BAD SCRIPT HAS BEEN FOUND
}
return true;
}
/**
* Perform an array scan
*
* *Note* Although more practical to pass the array parameter $array by reference ("&$array"), apparently in PHP you cannot loop through an array passed as a reference parameter.
* To attempt to loop through the array passed via reference parameter results in the foreach construct loop retrieving the first element pair only and never advances beyond that, causing
* an infinite amount of attempts to advance the array pointer when it apparently can never advance. This is why instead the array is passed and returned
*
* @access private
* @param array $array
* @param mixed $arrayName
* @return array $array
*/
function &array_scan($array, $arrayName) {
if (is_array($array) && @sizeof($array) > 0) {
@reset($array);
foreach ($array as $key => $val) {
$this->setData($val);
$this->scan($key, $arrayName);
$array[$key] = $this->getData();
if (!$this->dbAP->isSuccessful) return $array; // STOP ON THE FIRST ERROR, NO NEED TO PROCESS FURTHER
}
}
return $array;
}
/**
* Perform logging
*
* @acces private
* @param mixed $key
* @param mixed $varname
*/
function &log($key = '', $varname = '') { // STATIC VOID METHOD
// LOG CHANGES IF REQUIRED TO DO SO
global $section, $action;
if (!$this->data) {
if ($this->hasFoundEmbeddedExec) $logMsg = "Error: Embedded potential \"exec()\" function ";
if ($this->hasFoundSQLInjection) $logMsg = "Error: Embedded potential SQL injection script ";
if ($this->hasFoundMaliciousScript) $logMsg = "Error: Embedded potential malicious script ";
if ($this->hasFoundEmbeddedExec || $this->hasFoundSQLInjection || $this->hasFoundMaliciousScript) {
$logMsg .= 'found within text ';
if ($key && $varname) $logMsg .= "within $varname" . "['$key'] ";
if ($section || $action || $_REQUEST['hasLoggedIn']) $logMsg .= ' performing:';
if ($section) $logMsg .= $section;
if ($section && $action) $logMsg .= ',';
if ($action) $logMsg .= " $action";
if (!$section && !$action && $_REQUEST['hasLoggedIn']) $logMsg .= ' login';
if ($this->willLog) $logMsg .= '; action and your IP address has been logged';
if ($this->willLog && class_exists('LogGenerator') && is_object($this->log) && @is_a($this->log, 'LogGenerator')) $this->log->performLog($logMsg);
$this->dbAP->setErrorArray(array('action' => nl2br(htmlspecialchars($logMsg))));
}
}
}
/**
* Perform scan on $this->data
*
* @access private
* @param mixed $key (optional) Array key if applicable for logging scanning errors
* @param mixed $varname (optional) Name of variable (or collection object) affected by scanning violation
* @return mixed $this->data
* @see actual_path
*/
function &scan($key = '', $varname = '') { // STATIC STRING METHOD
global $willStripHTML, $willStripHTMLFromMetadata, $hasSafeHTMLFile, $safeHTMLFullFileName, $tclLibraryPath;
if (preg_match('/<![^!>]+>/', $this->data)) {
$this->data = ''; // STRIP $this->data IF FOUND <!.. !>
$this->hasFoundEmbeddedExec = true;
$this->dbAP->isSuccessful = false;
}
if (preg_match("/';/", $this->data)) {
$this->data = ''; // STRIP $this->data IF FOUND '; POTENTIAL SQL INJECTION
$this->hasFoundSQLInjection = true;
$this->dbAP->isSuccessful = false;
}
foreach (array('script', 'embed', 'object') as $tag) {
if (preg_match("/<$tag" . '[^>]*>/i', $this->data)) {
$this->data = ''; // STRIP $this->data IF FOUND POTENTIAL HARMFUL HTML EMBEDDED VIRAL SEQUENCES
$this->hasFoundMaliciousScript = true;
$this->dbAP->isSuccessful = false;
}
}
if ($willStripHTML) $this->data = strip_tags($this->data); // STRIP **ALL** HTML
// ONLY STRIP "UNSAFE" HTML TAGS WHILE LEAVING "SAFE" ONES (AS DEFINED WITHIN $safeHTMLFullFileName)
if (!$willStripHTML && $willStripHTMLFromMetadata && $hasSafeHTMLFile && is_dir(actual_path($tclLibraryPath)) && is_file(actual_path($safeHTMLFullFileName)))
$this->data = @safe_html($this->data, $tclLibraryPath, $this->dbAP);
$this->log($key, $varname);
return $this->data;
}
}