Index: trunk/kernel/include/debugger.php
===================================================================
--- trunk/kernel/include/debugger.php	(revision 902)
+++ trunk/kernel/include/debugger.php	(revision 903)
@@ -1,652 +1,660 @@
 <?php
 	
 	if(!defined('DBG_OPTIONS')) define('DBG_OPTIONS',0);
 	
 	if(!defined('DBG_USE_HIGHLIGHT')) define('DBG_USE_HIGHLIGHT',1);	
 	
 	if(!defined('DBG_USE_SHUTDOWN_FUNC')) define('DBG_USE_SHUTDOWN_FUNC',1);
 	if(!defined('DBG_HANDLE_ERRORS')) define('DBG_HANDLE_ERRORS', isset($_REQUEST['debug_host']) ? 0 : 1);
 	
 	if(!defined('DOC_ROOT')) define('DOC_ROOT',$_SERVER['DOCUMENT_ROOT']);
 	if(!defined('WINDOWS_ROOT')) define('WINDOWS_ROOT','w:');
 	
 	if(!defined('WINDOWS_EDITOR'))
 	{
 		$dbg_editor = 0;
 		$dbg_editors[0] = Array('editor' => '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 $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.']<br>');
 			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.']<br>');
     		return ($this->Options & $this->OptionsMap[$name]) == $this->OptionsMap[$name];
 		}
 		
 		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 = '<b class="debug_error">'.$this->getErrorNameByCode($Data['no']).'</b>: '.$Data['str'];
 					$ret .= ' in <b>'.$fileLink.'</b> on line <b>'.$Data['line'].'</b>';
 					return $ret;
 					break;
 				
 				case 'var_dump':
 					$ret = $this->highlightString( print_r($Data['value'], true) );
 					return addslashes($ret);
 					break;
 					
 				case 'trace':
 					$trace =& $Data['trace'];
 					$i = 0; $traceCount = count($trace);
 					$ret = '';
 					while($i < $traceCount)
 					{
 						$traceRec =& $trace[$i];
 						$argsID = 'trace_args_'.$dataIndex.'_'.$i;
 						$ret .= '<a href="javascript:toggleTraceArgs(\''.$argsID.'\');" title="Show/Hide Function Arguments"><b>Function</b></a>: '.$this->getFileLink($traceRec['file'],$traceRec['line'],$traceRec['class'].$traceRec['type'].$traceRec['function']).'';
 						$ret .= ' in <b>'.basename($traceRec['file']).'</b> on line <b>'.$traceRec['line'].'</b><br>';
 						
 						// ensure parameter value is not longer then 200 symbols
 						$this->processTraceArguments($traceRec['args']);
 						
 						$args = $this->highlightString(print_r($traceRec['args'], true));
 						$ret .= '<div id="'.$argsID.'" style="display: none;">'.$args.'</div>';
 						
 						$i++;
 					}
 					return $ret;
 					break;
 				
 				case 'profiler':
 					$profileKey = $Data['profile_key'];
 					$Data =& $this->ProfilerData[$profileKey];
 					$runtime = ($Data['ends'] - $Data['begins']); // in seconds
 					return '<b>Name</b>: '.$Data['description'].'<br><b>Runtime</b>: '.$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('/(SELECT|UPDATE|REPLACE|INSERT|DELETE|VALUES|FROM|LEFT JOIN|WHERE|HAVING|GROUP BY|ORDER BY) /is', "\n\t$1 ",$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('<?php '.$string.'?>', true);
 				return preg_replace('/&lt;\?(.*)php (.*)\?&gt;/s','$2',$string);
 			}
 			else
 			{
 				return $string;
 			}
 		}
 		
 		function getFileLink($file, $lineno = 1, $title = '')
 		{
 			if(!$title) $title = $file;
 			return '<a href="javascript:editFile(\''.$this->getLocalFile($file).'\','.$lineno.');" title="'.$file.'">'.$title.'</a>';	
 		}
 		
 		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'] .= '<br>'.$html;
 					break;
 				case 'prepend':
 					$this->Data[$index]['html'] = $this->Data[$index]['html'].'<br>'.$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: <b>'.$this->getFileLink($script,1,basename($script)).'</b> (<b>'.dirname($script).'</b>)');
 			ob_start();
 			?>
 			<table width="100%" border="0" cellspacing="0" cellpadding="4" class="flat_table">
 				<thead style="font-weight: bold;">
 					<td width="20">Src</td><td>Name</td><td>Value</td>
 				</thead>
 			<?php
 				foreach($_REQUEST as $key => $value)
 				{
 					if( !is_array($value) && trim($value) == '' )
 					{
 						$value = '<b class="debug_error">no value</b>';
 					}
 					else
 					{
 						$value = htmlspecialchars(print_r($value, true));
 					}
 					$src = isset($_GET[$key]) ? 'GE' : (isset($_POST[$key]) ? 'PO' : (isset($_COOKIE[$key]) ? 'CO' : '?') );
 					echo '<tr><td>'.$src.'</td><td>'.$key.'</td><td>'.$value.'</td></tr>';
 				}
 			?> 
 			</table>
 			<?php
 			$this->appendHTML( ob_get_contents() );
 			ob_end_clean();
 		}
 		
 		function appendSession()
 		{
 			if( isset($_SESSION)&&$_SESSION )
 			{
 				$this->appendHTML('PHP Session: [<b>'.ini_get('session.name').'</b>]');
 				$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('<a href="javascript:toggleDebugLayer();">Hide Debugger</a>');
+			$this->appendHTML('<a href="javascript:toggleDebugLayer(27);">Hide Debugger</a>');
 			$this->moveToBegin(1);
 			
 			$i = 0; $lineCount = count($this->Data);
 			ob_start();
 			?>
 				<style type="text/css">
 					.flat_table TD {
 						border: 1px solid buttonface;
 						border-width: 1 1 0 0;
 					
 					}
 					
 					.debug_layer_table {
-						border: 1px solid red;
-						border-width: 0 0 1 1;
+						border-collapse: collapse;
 						width: 480px;
 					}
 					
 					.debug_text, .debug_row_even TD, .debug_row_odd TD {
 						color: #000000;
 						font-family: Verdana;
 						font-size: 11px;
 						word-wrap: break-word;
 					}
 					
 					.debug_cell {
-						border: 1px solid red;
-						border-width: 1 1 0 0;
+						border: 1px solid #FF0000;
+						padding: 2px;
 						word-wrap: break-word;
 					}
 					
 					.debug_row_even {
 						background-color: #CCCCFF;
 					}
 					
 					.debug_row_odd {
 						background-color: #FFFFCC;
 					}
 					
 					.debug_layer_container {
 						left: 2px;
 						top: 1px;
 						width: 500px;
 						z-index: +1000;
 						position: absolute;
 						overflow: auto;
 						border: 2px solid;
 						padding: 3px;
 						border-top-color: threedlightshadow;
 						border-left-color: threedlightshadow;
 						border-right-color: threeddarkshadow;
 						border-bottom-color: threeddarkshadow;
 						background-color: buttonface;
 					}
 					
 					.debug_layer {
 						padding: 0px;
 						width: 480px;
 					}
 					
 					.debug_error {
 						color: #FF0000;
 					}
 				</style>
 				<div id="debug_layer" class="debug_layer_container" style="display: none;">
 					<div class="debug_layer">
 						<table width="100%" cellpadding="0" cellspacing="1" border="0" class="debug_layer_table">
 			<?php
 			while ($i < $lineCount)
 			{
 				echo '<tr class="debug_row_'.(($i % 2) ? 'odd' : 'even').'"><td class="debug_cell">'.$this->prepareHTML($i).'</td></tr>';
 				$i++;
 			}
 			?>
 						</table>
 					</div>
 				</div>
 				<script language="javascript">
 					function getEventKeyCode($e)
 					{
 						var $KeyCode = 0;
 						if($e.keyCode) $KeyCode = $e.keyCode;
 						else if($e.which) $KeyCode = $e.which;
 						return $KeyCode;
 					}
 				
 					function keyProcessor($e)
 					{
 						if(!$e) $e = window.event;
 						var $KeyCode = getEventKeyCode($e);
-						//alert(showProps($e));
-						if($KeyCode == 123 || $KeyCode == 27) // F12 or ESC
+						if($KeyCode==123||$KeyCode==27) // F12 or ESC
 						{
-							toggleDebugLayer();
+							toggleDebugLayer($KeyCode);
 							$e.cancelBubble = true;
 							if($e.stopPropagation) $e.stopPropagation();
 						}
 					}
 					
-					function toggleDebugLayer()
+					function toggleDebugLayer($KeyCode)
 					{
+						var $isVisible=false;
 						var $DebugLayer = document.getElementById('debug_layer');
 						if( typeof($DebugLayer) != 'undefined' )
 						{
+							$isVisible = ($DebugLayer.style.display == 'none')?false:true;
+							if(!$isVisible&&$KeyCode==27) return false;
+							
 							resizeDebugLayer(null);
-							$DebugLayer.style.display = ($DebugLayer.style.display == 'none') ? 'block' : 'none';
+							$DebugLayer.style.display = $isVisible?'none':'block';
 						}
 					}
 					
 					function prepareSizes($Prefix)
 					{
 						var $ret = '';
 						$ret = eval('document.body.'+$Prefix+'Top')+'; ';
 						$ret += eval('document.body.'+$Prefix+'Left')+'; ';
 						$ret += eval('document.body.'+$Prefix+'Height')+'; ';
 						$ret += eval('document.body.'+$Prefix+'Width')+'; ';	
 						return $ret;
 					}
 					
 					function resizeDebugLayer($e)
 					{
 						if(!$e) $e = window.event;
 						var $DebugLayer = document.getElementById('debug_layer');
 						var $TopMargin = 1;
 						if( typeof($DebugLayer) != 'undefined' )
 						{
 							$DebugLayer.style.top = parseInt(document.body.offsetTop + document.body.scrollTop) + $TopMargin;
 							$DebugLayer.style.height = document.body.clientHeight - $TopMargin - 5;
 						}
 						window.parent.status = 'OFFSET: '+prepareSizes('offset')+' | SCROLL: '+prepareSizes('scroll')+' | CLIENT: '+prepareSizes('client');
 						window.parent.status += 'DL Info: '+$DebugLayer.style.top+'; S.AH: '+screen.availHeight;
 						return true;
 					}
 					
 					function SetClipboard($data)
 					{
 						if (window.clipboardData)
 						{
 							window.clipboardData.setData('Text', $data);
 						}
 						else if (window.netscape)
 						{
 							//netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 							var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
 							if (!clip) return;
 
 							var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
 							if (!trans) return;
 
 							trans.addDataFlavor('text/unicode');
 							var str = new Object();
 							var len = new Object();
 							var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
 
 							var $copytext=$data;
 
 							str.data=$copytext;
 
 							trans.setTransferData("text/unicode",str,$copytext.length*2);
 							var clipid=Components.interfaces.nsIClipboard;
 							if (!clip) return false;
 
 							clip.setData(trans,null,clipid.kGlobalClipboard);
 						}
 
 					}
 					
 					function showProps($Obj, $Name)
 					{
 						var $ret = '';
 						for($Prop in $Obj)
 						{
 							$ret += $Name+'.'+$Prop+' = '+$Obj[$Prop]+"\n";
 						}
 						return $ret;
 					}
 					
 					function editFile($fileName,$lineNo)
 					{
+						if(!document.all)
+						{
+							alert('Only works in IE');
+							return;
+						}
+						
 						var $editorPath = '<?php echo defined('WINDOWS_EDITOR') ? addslashes(WINDOWS_EDITOR) : '' ?>';
 						if($editorPath)
 						{
 							var $obj = new ActiveXObject("LaunchinIE.Launch");
 							$editorPath = $editorPath.replace('%F',$fileName);
 							$editorPath = $editorPath.replace('%L',$lineNo);
 							$obj.LaunchApplication($editorPath);
 						}
 						else
 						{
 							alert('Editor path not defined!');	
 						}
 					}
 					
 					function toggleTraceArgs($ArgsLayerID)
 					{
 						var $ArgsLayer = document.getElementById($ArgsLayerID);
 						$ArgsLayer.style.display = ($ArgsLayer.style.display == 'none') ? 'block' : 'none';
 					}
 					
 					
 					document.onkeydown = keyProcessor;
 					window.onresize = resizeDebugLayer;
 					window.onscroll = resizeDebugLayer;
 					window.focus();
 					if( typeof($isFatalError) != 'undefined' && $isFatalError == 1 )
 					{
 						toggleDebugLayer();
 						document.getElementById('debug_layer').scrollTop = 10000000;
 					}
 				</script>
 			<?php
 			
 			if($returnResult)
 			{
 				$ret = ob_get_contents();
 				ob_clean();
 				return $ret;
 			}
 			else
 			{
 				ob_end_flush();
 			}
 		}
 		
 		/**
 		 * User-defined error handler
 		 *
 		 * @param int $errno
 		 * @param string $errstr
 		 * @param string $errfile
 		 * @param int $errline
 		 * @param array $errcontext
 		 */
 		function saveError($errno, $errstr, $errfile = '', $errline = '', $errcontext = '')
 		{
 			//echo '<b>error</b> ['.$errno.'] = ['.$errstr.']<br>';
 			$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 = '[<b>EVAL</b>, line <b>'.$errline.'</b>]: '.$errstr;
 				$tmpStr = $errfile;
 				$pos = strpos($tmpStr,'(');
 				$errfile = substr($tmpStr,0,$pos);
 				$pos++;
 				$errline = substr($tmpStr,$pos,strpos($tmpStr,')',$pos)-$pos);
 			}
 			
 			$this->Data[] = Array('no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline, 'context' => $errcontext, 'debug_type' => 'error');
 			
 			if( substr($errorType,0,5) == 'Fatal')
 			{
 				echo '<script language="javascript">var $isFatalError = 1;</script>';
 				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') );
 	
 	
 ?>
\ No newline at end of file

Property changes on: trunk/kernel/include/debugger.php
___________________________________________________________________
Modified: cvs2svn:cvs-rev
## -1 +1 ##
-1.14
\ No newline at end of property
+1.15
\ No newline at end of property