'c:\Program Files\UltraEdit\uedit32.exe', 'params' => '%F/%L');
$dbg_editors[1] = Array('editor' => 'c:\Program Files\Zend\ZendStudio-4.0Beta\bin\ZDE.exe', 'params' => '%F');
define('WINDOWS_EDITOR',$dbg_editors[$dbg_editor]['editor'].' '.$dbg_editors[$dbg_editor]['params']);
unset($dbg_editors,$dbg_editor);
}
class Debugger
{
/**
* Debugger data for building report
*
* @var Array
*/
var $Data = Array();
var $ProfilerData = Array();
var $RecursionStack = Array(); // prevent recursion when processing debug_backtrace() function results
var $TraceNextError=false;
var $Options = 0;
var $OptionsMap = Array('shutdown_func' => 1, 'error_handler' => 2,
'output_buffer' => 4, 'highlight_output' => 8);
function Debugger()
{
$this->appendRequest();
}
function initOptions()
{
}
function setOption($name,$value)
{
if( !isset($this->OptionsMap[$name]) ) die('undefined debugger option: ['.$name.']
');
if($value)
{
$this->Options|=$this->OptionsMap[$name];
}
else
{
$this->Options=$this->Options&~$this->OptionsMap[$name];
}
}
function getOption($name)
{
if( !isset($this->OptionsMap[$name]) ) die('undefined debugger option: ['.$name.']
');
return ($this->Options & $this->OptionsMap[$name]) == $this->OptionsMap[$name];
}
/**
* Set's flag, that next error that occurs will
* be prepended by backtrace results
*
*/
function traceNext()
{
$this->TraceNextError=true;
}
function dumpVars()
{
$dumpVars = func_get_args();
foreach($dumpVars as $varValue)
{
$this->Data[] = Array('value' => $varValue, 'debug_type' => 'var_dump');
}
}
function prepareHTML($dataIndex)
{
$Data =& $this->Data[$dataIndex];
if($Data['debug_type'] == 'html') return $Data['html'];
switch($Data['debug_type'])
{
case 'error':
$fileLink = $this->getFileLink($Data['file'],$Data['line']);
$ret = ''.$this->getErrorNameByCode($Data['no']).': '.$Data['str'];
$ret .= ' in '.$fileLink.' on line '.$Data['line'].'';
return $ret;
break;
case 'var_dump':
$ret = $this->highlightString( print_r($Data['value'], true) );
return addslashes($ret);
break;
case 'trace':
ini_set('memory_limit','500M');
$trace =& $Data['trace'];
//return 'sorry';
//return $this->highlightString(print_r($trace,true));
$i = 0; $traceCount = count($trace);
$ret = '';
while($i < $traceCount)
{
$traceRec =& $trace[$i];
$argsID = 'trace_args_'.$dataIndex.'_'.$i;
if(isset($traceRec['file']))
{
$ret .= 'Function: '.$this->getFileLink($traceRec['file'],$traceRec['line'],$traceRec['class'].$traceRec['type'].$traceRec['function']);
$ret .= ' in '.basename($traceRec['file']).' on line '.$traceRec['line'].'
';
}
else
{
$ret .= 'no file information available';
}
// ensure parameter value is not longer then 200 symbols
$this->processTraceArguments($traceRec['args']);
$args = $this->highlightString(print_r($traceRec['args'], true));
$ret .= '
'.$args.'
';
$i++;
}
return $ret;
break;
case 'profiler':
$profileKey = $Data['profile_key'];
$Data =& $this->ProfilerData[$profileKey];
$runtime = ($Data['ends'] - $Data['begins']); // in seconds
return 'Name: '.$Data['description'].'
Runtime: '.$runtime.'s';
break;
default:
return 'incorrect debug data';
break;
}
}
function processTraceArguments(&$traceArgs)
{
foreach ($traceArgs as $argID => $argValue)
{
if( is_array($argValue) || is_object($argValue) )
{
if(is_object($argValue) && !in_array(get_class($argValue),$this->RecursionStack) )
{
// object & not in stack - ok
array_push($this->RecursionStack, get_class($argValue));
settype($argValue,'array');
$this->processTraceArguments($argValue);
array_pop($this->RecursionStack);
}
elseif(is_object($argValue) && in_array(get_class($argValue),$this->RecursionStack) )
{
// object & in stack - recursion
$traceArgs[$argID] = '**** RECURSION ***';
}
else
{
// normal array here
$this->processTraceArguments($argValue);
}
}
else
{
$traceArgs[$argID] = $this->cutStringForHTML($traceArgs[$argID]);
}
}
}
function cutStringForHTML($string)
{
if( strlen($string) > 200 ) $string = substr($string,0,50).' ...';
return $string;
}
/**
* Format SQL Query using predefined formatting
* and highlighting techniques
*
* @param string $sql
* @return string
*/
function formatSQL($sql)
{
$sql = preg_replace('/(\n|\t| )+/is',' ',$sql);
$sql = preg_replace('/(CREATE TABLE|DROP TABLE|SELECT|UPDATE|REPLACE|INSERT|DELETE|VALUES|FROM|LEFT JOIN|WHERE|HAVING|GROUP BY|ORDER BY) /is', "\n\t$1 ",$sql);
return $this->highlightString($sql);
}
function highlightString($string)
{
if( defined('DBG_USE_HIGHLIGHT')&&DBG_USE_HIGHLIGHT )
{
$string = highlight_string('', true);
return preg_replace('/<\?(.*)php (.*)\?>/s','$2',$string);
}
else
{
return $string;
}
}
function getFileLink($file, $lineno = 1, $title = '')
{
if(!$title) $title = $file;
return ''.$title.'';
}
function getLocalFile($remoteFile)
{
return str_replace(DOC_ROOT, WINDOWS_ROOT, $remoteFile);
}
function appendTrace()
{
$trace = debug_backtrace();
array_shift($trace);
$this->Data[] = Array('trace' => $trace, 'debug_type' => 'trace');
}
function appendHTML($html)
{
$this->Data[] = Array('html' => $html,'debug_type' => 'html');
}
/**
* Change debugger info that was already generated before.
* Returns true if html was set.
*
* @param int $index
* @param string $html
* @param string $type = {'append','prepend','replace'}
* @return bool
*/
function setHTMLByIndex($index,$html,$type='append')
{
if( !isset($this->Data[$index]) || $this->Data[$index]['debug_type'] != 'html' )
{
return false;
}
switch ($type)
{
case 'append':
$this->Data[$index]['html'] .= '
'.$html;
break;
case 'prepend':
$this->Data[$index]['html'] = $this->Data[$index]['html'].'
'.$html;
break;
case 'replace':
$this->Data[$index]['html'] = $html;
break;
}
return true;
}
/**
* Move $debugLineCount lines of input from debug output
* end to beginning.
*
* @param int $debugLineCount
*/
function moveToBegin($debugLineCount)
{
$lines = array_splice($this->Data,count($this->Data)-$debugLineCount,$debugLineCount);
$this->Data = array_merge($lines,$this->Data);
}
function appendRequest()
{
$script = $_SERVER['PATH_TRANSLATED'];
$this->appendHTML('ScriptName: '.$this->getFileLink($script,1,basename($script)).' ('.dirname($script).')');
ob_start();
?>
Src | Name | Value |
$value)
{
if( !is_array($value) && trim($value) == '' )
{
$value = 'no value';
}
else
{
$value = htmlspecialchars(print_r($value, true));
}
$src = isset($_GET[$key]) ? 'GE' : (isset($_POST[$key]) ? 'PO' : (isset($_COOKIE[$key]) ? 'CO' : '?') );
echo ''.$src.' | '.$key.' | '.$value.' |
';
}
?>
appendHTML( ob_get_contents() );
ob_end_clean();
}
function appendSession()
{
if( isset($_SESSION)&&$_SESSION )
{
$this->appendHTML('PHP Session: ['.ini_get('session.name').']');
$this->dumpVars($_SESSION);
$this->moveToBegin(2);
}
}
function profileStart($key, $description)
{
$timeStamp = $this->getMoment();
$this->ProfilerData[$key] = Array('begins' => $timeStamp, 'ends' => 5000, 'debuggerRowID' => count($this->Data), 'description' => $description);
$this->Data[] = array('profile_key' => $key, 'debug_type' => 'profiler');
}
function profileFinish($key)
{
$this->ProfilerData[$key]['ends'] = $this->getMoment();
}
function getMoment()
{
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
}
function generateID()
{
list($usec, $sec) = explode(" ",microtime());
$id_part_1 = substr($usec, 4, 4);
$id_part_2 = mt_rand(1,9);
$id_part_3 = substr($sec, 6, 4);
$digit_one = substr($id_part_1, 0, 1);
if ($digit_one == 0) {
$digit_one = mt_rand(1,9);
$id_part_1 = ereg_replace("^0","",$id_part_1);
$id_part_1=$digit_one.$id_part_1;
}
return $id_part_1.$id_part_2.$id_part_3;
}
function getErrorNameByCode($errorCode)
{
switch($errorCode)
{
case E_USER_ERROR:
return 'Fatal Error';
break;
case E_WARNING:
case E_USER_WARNING:
return 'Warning';
break;
case E_NOTICE:
case E_USER_NOTICE:
return 'Notice';
break;
default:
return '';
break;
}
}
/**
* Generates report
*
*/
function printReport($returnResult = false)
{
// show php session if any
$this->appendSession();
// ensure, that 1st line of debug output always is this one:
$this->appendHTML('Hide Debugger');
$this->moveToBegin(1);
$i = 0; $lineCount = count($this->Data);
ob_start();
?>
'.$this->prepareHTML($i).' | ';
$i++;
}
?>
error ['.$errno.'] = ['.$errstr.']
';
$errorType = $this->getErrorNameByCode($errno);
if(!$errorType)
{
trigger_error('Unknown error type ['.$errno.']', E_USER_ERROR);
return false;
}
if( strpos($errfile,'eval()\'d code') !== false )
{
$errstr = '[EVAL, line '.$errline.']: '.$errstr;
$tmpStr = $errfile;
$pos = strpos($tmpStr,'(');
$errfile = substr($tmpStr,0,$pos);
$pos++;
$errline = substr($tmpStr,$pos,strpos($tmpStr,')',$pos)-$pos);
}
if($this->TraceNextError)
{
$this->appendTrace();
$this->TraceNextError=false;
}
$this->Data[] = Array('no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline, 'context' => $errcontext, 'debug_type' => 'error');
if( substr($errorType,0,5) == 'Fatal')
{
echo '';
exit;
}
}
function saveToFile($msg)
{
$fp = fopen($_SERVER['DOCUMENT_ROOT'].'/vb_debug.txt', 'a');
fwrite($fp,$msg."\n");
fclose($fp);
}
}
function ConstOn($const_name)
{
return defined($const_name)&&constant($const_name);
}
$debugger = new Debugger();
if(ConstOn('DBG_HANDLE_ERRORS')) set_error_handler( array(&$debugger,'saveError') );
if(ConstOn('DBG_USE_SHUTDOWN_FUNC')) register_shutdown_function( array(&$debugger,'printReport') );
?>