Index: branches/5.3.x/core/kernel/utility/debugger/debugger.js
===================================================================
--- branches/5.3.x/core/kernel/utility/debugger/debugger.js	(revision 15947)
+++ branches/5.3.x/core/kernel/utility/debugger/debugger.js	(revision 15948)
@@ -1,608 +1,636 @@
 function DebugReq() {}
 
 DebugReq.timeout = 5 * 60 * 1000; // 5 minutes
 
 DebugReq.makeRequest = function(p_url, p_busyReq, p_progId, p_successCallBack, p_errorCallBack, p_pass, p_object) {
 	//p_url: the web service url
 	//p_busyReq: is a request for this object currently in progress?
 	//p_progId: element id where progress HTML should be shown
 	//p_successCallBack: callback function for successful response
 	//p_errorCallBack: callback function for erroneous response
 	//p_pass: string of params to pass to callback functions
 	//p_object: object of params to pass to callback functions
 	if (p_busyReq) {
 		return;
 	}
 	var req = DebugReq.getRequest();
 	if (req != null) {
 		p_busyReq = true;
 		DebugReq.showProgress(p_progId);
 		req.onreadystatechange = function() {
 			if (req.readyState == 4) {
 				p_busyReq = false;
 				window.clearTimeout(toId);
 				if (req.status == 200) {
 					p_successCallBack(req,p_pass,p_object);
 				} else {
 					p_errorCallBack(req,p_pass,p_object);
 				}
 			}
 		}
 		var $ajax_mark = (p_url.indexOf('?') ? '&' : '?') + 'ajax=yes';
 		req.open('GET', p_url + $ajax_mark, true);
 		req.setRequestHeader('If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT');
 		req.send(null);
 		var toId = window.setTimeout( function() {if (p_busyReq) req.abort();}, DebugReq.timeout );
 	}
 }
 
 DebugReq.getRequest = function() {
 	var xmlHttp;
 	try { xmlHttp = new ActiveXObject('MSXML2.XMLHTTP'); return xmlHttp; } catch (e) {}
 	try { xmlHttp = new ActiveXObject('Microsoft.XMLHTTP'); return xmlHttp; } catch (e) {}
 	try { xmlHttp = new XMLHttpRequest(); return xmlHttp; } catch(e) {}
 	return null;
 }
 
 DebugReq.showProgress = function(p_id) {
 	$Debugger.AppendRow(DebugReq.getProgressHtml());
 }
 
 DebugReq.getProgressHtml = function() {
 	return 'Loading ...';
 }
 
 DebugReq.getErrorHtml = function(p_req) {
 	//TODO: implement accepted way to handle request error
 	return "<p>" + "(" + p_req.status + ") " + p_req.statusText + "</p>"
 }
 
 // Debugger
 function Debugger($params) {
 	this.RowSeparator = '';
+	this.FilterTypes = $params['FilterTypes'];
 	this.IsFatalError = false;
 	this.ErrorsCount = 0;
 	this.SQLCount = 0;
 	this.SQLTime = 0;
 	this.ScriptTime = 0;
 	this.ScriptMemory = 0;
 	this.Shortcut = 'F12';
 
 	for (var $param_name in $params) {
 		this[$param_name] = $params[$param_name];
 	}
 
 	this.IsQueried = false;
 	this.IsVisible = false;
 	this.DebuggerDIV = document.getElementById('debug_layer');
 	this.DebuggerTable = document.getElementById('debug_table');
 	this.RowCount = 0;
 	this.busyRequest = false;
 
 	this.DragObject = null;
 	this.LastDragObject = null;
 	this.MouseOffset = [0,0];
 	this.ResizeHappening = false;
 	this.ResizeTimer = null;
 	this.InitialPos = null;
 
 //	window.$Debugger = this; // this should be uncommented in case if debugger variable is not $Debugger
 	this.AddEvent(window, 'scroll', function (ev) { window.$Debugger.Resize(ev); });
 	this.AddEvent(window, 'resize', function (ev) { window.$Debugger.Resize(ev); });
 	this.AddEvent(document, 'keydown', function (ev) { window.$Debugger.KeyDown(ev); }); // don't work in IE
 }
 
 Debugger.prototype.createEnvironment = function($outer_width, $inner_width) {
 	if (!this.DebuggerDIV) {
 		// when debugger wasn't added already
 		var $container = document.createElement('DIV');
 		$container.id = 'debug_layer';
 		$container.className = 'debug_layer_container';
 		$container.style.display = 'none';
 		$container.style.width = $outer_width + 'px';
 
 		var $debug_layer = document.createElement('DIV');
 		$debug_layer.className = 'debug_layer';
 		$debug_layer.style.width = $inner_width + 'px';
 		$container.insertBefore($debug_layer, $container.firstChild);
 
 		var $table = document.createElement('TABLE');
 		$table.style.width = '100%';
 		$table.className = 'debug_layer_table';
 		$table.style.width = $inner_width + 'px';
 		$debug_layer.insertBefore($table, $debug_layer.firstChild);
 
 		var $tbody = document.createElement('TBODY');
 		$tbody.id = 'debug_table';
 		$table.insertBefore($tbody, $table.firstChild);
 
 		var $body = document.getElementsByTagName('BODY')[0];
 		$body.insertBefore($container, $body.lastChild);
 
 		this.DebuggerDIV = document.getElementById('debug_layer');
 		this.DebuggerTable = document.getElementById('debug_table');
 	}
 	else {
 		this.Clear();
 	}
 }
 
 Debugger.prototype.SetOpacity = function(opacity)
 {
 	this.DebuggerToolbar.style.opacity = (opacity / 100);
 	this.DebuggerToolbar.style.MozOpacity = (opacity / 100);
 	this.DebuggerToolbar.style.KhtmlOpacity = (opacity / 100);
 	this.DebuggerToolbar.style.filter = "alpha(opacity=" + opacity + ")";
 }
 
 Debugger.prototype.ToolbarClick = function ($button) {
 	switch ($button.id) {
 		case 'dbg_ReloadFrame':
 			self.location.reload();
 			break;
 
 		case 'dbg_ShowDebugger':
 			this.Toggle();
 			break;
 
 		case 'dbg_TurnOff':
 			var $exdate = new Date();
 
 			$exdate.setDate( $exdate.getDate() + 365 );
 			document.cookie = 'debug_off=1; expires=' + $exdate.toUTCString() + '; path=' + this.BasePath + '/';
 			self.location.reload();
 			break;
 	}
 }
 
 Debugger.prototype.jQueryFound = function () {
 	return typeof jQuery == 'function';
 }
 
 Debugger.prototype.AddToolbar = function($var_name) {
 	if (document.getElementById('debug_toolbar_span')) {
 		// toolbar was already created before
 		if (this.jQueryFound()) {
 			$('#debug_toolbar_span').remove();
 		}
 		else {
 			return ;
 		}
 	}
 
 	var $span = document.createElement('SPAN');
 	$span.style.position = 'absolute';
 	$span.style.zIndex= 99;
 	$span.style.top = '0px';
 	$span.style.left = '0px';
 	$span.id = 'debug_toolbar_span';
 	document.body.style.textAlign = 'left';
 
 	var $toolbar_content = '<td class="dbg-button" id="dbg_ReloadFrame" onclick="' + $var_name + '.ToolbarClick(this);">Reload Frame</td>';
 
 	if (this.ErrorsCount > 0) {
 		$toolbar_content += '<td class="dbg-separator"></td><td class="dbg-button debug_error" style="font-weight: bold;" id="dbg_ShowDebugger" onclick="' + $var_name + '.ToolbarClick(this);">Show Debugger (' + this.ErrorsCount + ' errors)</td>';
 	}
 	else {
 		$toolbar_content += '<td class="dbg-button" id="dbg_ShowDebugger" onclick="' + $var_name + '.ToolbarClick(this);">Show Debugger</td>';
 	}
 
 	$toolbar_content += '<td class="dbg-button" id="dbg_TurnOff" onclick="' + $var_name + '.ToolbarClick(this);">Turn Off</td>';
 
 	if (this.SQLCount > 0) {
 		$toolbar_content += '<td class="dbg-separator"></td><td style="cursor: move"><strong>' + this.SQLCount + '</strong> sqls (' + this.SQLTime + ' s)</td>';
 	}
 
 	if (this.ScriptTime > 0) {
 		$toolbar_content += '<td class="dbg-separator"></td><td style="cursor: move">' + this.ScriptTime + ' s (' + this.ScriptMemory + ')</td>';
 	}
 
 	$span.innerHTML = '<table style="height: 30px" cellpadding="0" cellspacing="3" class="dbg-toolbar"><tr>' + $toolbar_content + '</tr></table>';
 
 	this.DebuggerToolbar = $span;
 	this.SetOpacity(20);
 	$span.onmouseover = function() {
 		$Debugger.SetOpacity(100);
 	}
 	$span.onmouseout = function() {
 		$Debugger.SetOpacity(20);
 	}
 
 	var $body = document.getElementsByTagName('BODY')[0];
 	$body.insertBefore($span, $body.firstChild);
 
 //	alert($span.offsetWidth)
 	this.MakeDragable('debug_toolbar_span', function() {}, function() {}, function() {});
 }
 
-Debugger.prototype.AppendRow = function($html) {
+Debugger.prototype.AppendRow = function($html, $row_type) {
+	$row_type = $row_type || 'other';
 	this.RowCount++;
 	var $tr = document.createElement('TR');
 	this.DebuggerTable.appendChild($tr);
 	$tr.className = 'debug_row_' + (this.RowCount % 2 ? 'odd' : 'even');
+
+	if ( this.RowCount > 2 ) {
+		$tr.setAttribute('data-row-type', $row_type);
+
+		if ( $row_type == 'error' ) {
+			document.getElementById('debug_row_' + (this.RowCount -1 )).setAttribute('data-row-type', 'error');
+		}
+	}
+
 	$tr.id = 'debug_row_' + this.RowCount;
 	var	$td = document.createElement('TD');
 	$td.className = 'debug_cell';
 	$td.innerHTML = $html;
 	$tr.appendChild($td);
 }
 
 Debugger.prototype.RemoveRow = function($row_index) {
 	this.DebuggerTable.deleteRow($row_index);
 	this.RowCount--;
 }
 
 Debugger.prototype.Clear = function() {
 	if (!this.IsQueried) return false;
 
 	while (this.DebuggerTable.rows.length) {
 		this.RemoveRow(0);
 	}
 
 	this.Toggle(27);
 	this.IsQueried = false;
 }
 
 Debugger.prototype.KeyDown = function($e) {
 	var $matched_parts = 0,
 		$KeyCode = this.GetKeyCode($e),
 		$shortcut_parts = this.Shortcut.toLowerCase().split('+');
 
 	$e = ($e) ? $e : event;
 
 	var $modifier_map = {
 		'ctrl': $e.ctrlKey,
 		'shift': $e.shiftKey,
 		'alt': $e.altKey,
 		'meta': $e.metaKey
 	};
 
 	for (var $i = 0; $i < $shortcut_parts.length; $i++) {
 		for (var $modifier in $modifier_map) {
 			if ( $shortcut_parts[$i] == $modifier && $modifier_map[$modifier] ) {
 				$matched_parts++;
 				break;
 			}
 		}
 
 		if ( this.getKeyCodeFromString($shortcut_parts[$i]) == $KeyCode ) {
 			$matched_parts++;
 		}
 	}
 
 	if ( $matched_parts == $shortcut_parts.length || $KeyCode == 27 ) {// F12 or ESC
 		this.Toggle($KeyCode);
 		this.StopEvent($e);
 	}
 }
 
 Debugger.prototype.getKeyCodeFromString = function($string) {
 	var $special_keys = {
 		'esc': 27,
 		'escape': 27,
 		'tab': 9,
 		'space': 32,
 		'return': 13,
 		'enter': 13,
 		'backspace': 8,
 
 		'scrolllock': 145,
 		'scroll_lock': 145,
 		'scroll': 145,
 		'capslock': 20,
 		'caps_lock': 20,
 		'caps': 20,
 		'numlock': 144,
 		'num_lock': 144,
 		'num': 144,
 
 		'pause': 19,
 		'break': 19,
 
 		'insert': 45,
 		'home': 36,
 		'delete': 46,
 		'end': 35,
 
 		'pageup': 33,
 		'page_up': 33,
 		'pu': 33,
 
 		'pagedown': 34,
 		'page_down': 34,
 		'pd': 34,
 
 		'left': 37,
 		'up': 38,
 		'right': 39,
 		'down': 40,
 
 		'f1': 112,
 		'f2': 113,
 		'f3': 114,
 		'f4': 115,
 		'f5': 116,
 		'f6': 117,
 		'f7': 118,
 		'f8': 119,
 		'f9': 120,
 		'f10': 121,
 		'f11': 122,
 		'f12': 123
 	};
 
 	$string = $string.toLowerCase();
 
 	if ( $special_keys[$string] !== undefined ) {
 		return $special_keys[$string];
 	}
 
 	return $string.charCodeAt(0);
 }
 
 Debugger.prototype.OpenDOMViewer = function() {
 	var $value = document.getElementById('dbg_domviewer').value;
 	DOMViewerObj = ($value.indexOf('"') != -1) ? document.getElementById( $value.substring(1,$value.length-1) ) : eval($value);
 	window.open(this.DOMViewerURL);
 	return false;
 }
 
 Debugger.prototype.GetKeyCode = function($e) {
 	$e = ($e) ? $e : event;
 	var charCode = ($e.charCode) ? $e.charCode : (($e.which) ? $e.which : $e.keyCode);
 
 	if ( charCode == 27 ) {
 		// don't lowercase ESC
 		return charCode;
 	}
 
 	return String.fromCharCode(charCode).toLowerCase().charCodeAt(0);
 }
 
 Debugger.prototype.StopEvent = function($e) {
 	$e = ($e) ? $e : event;
 	$e.cancelBubble = true;
 	if ($e.stopPropagation) $e.stopPropagation();
 }
 
+Debugger.prototype.Filter = function() {
+
+	var $new_filter = document.getElementById('dbg_filter').value;
+	var $container_class_name = 'debug_layer_container';
+
+	if ( $new_filter != '' ) {
+		for (var index = 0; index < this.FilterTypes.length; ++index) {
+			if ( this.FilterTypes[index] != $new_filter ) {
+				$container_class_name += ' dbg-' + this.FilterTypes[index] + '-row-hidden';
+			}
+		}
+	}
+
+	this.DebuggerDIV.className = $container_class_name;
+}
+
 Debugger.prototype.Toggle = function($KeyCode) {
 	if(!this.DebuggerDIV) return false;
 	this.IsVisible = this.DebuggerDIV.style.display == 'none' ? false : true;
 	if (!this.IsVisible && $KeyCode == 27) {
 		return false;
 	}
 
 	this.Resize(null);
 	if (!this.IsQueried) {
 		this.Query();
 	}
 
 	this.DebuggerDIV.style.display = this.IsVisible ? 'none' : 'block';
 }
 
 Debugger.prototype.Query = function() {
 	DebugReq.makeRequest(this.DebugURL, this.busyRequest, '', this.successCallback, this.errorCallback, '', this);
 }
 
 Debugger.prototype.successCallback = function(p_req, p_pass, p_object) {
 	if (p_pass == 'resetCache') {
 		alert('Requested action performed.');
 		return ;
 	}
 
 	var contents = p_req.responseText;
 
 	contents = contents.split(p_object.RowSeparator);
 	if (contents.length == 1) {
 		alert('error: '+p_req.responseText);
 		p_object.IsQueried = true;
 		return ;
 	}
 
 	for (var $i = 0; $i < contents.length - 1; $i++) {
-		p_object.AppendRow(contents[$i]);
+		$json = eval('(' + contents[$i] + ')');
+		p_object.AppendRow($json['html'], $json['row_type']);
 	}
 
 	if ( p_object.jQueryFound() ) {
 		var $stats_table = $('.dbg_stats_table:first').clone();
 		var $statistics_html = $( $('<div></div>').html($stats_table) ).html();
 
 		if ($statistics_html) {
 			$('.dbg_stats_table:first').remove();
 			p_object.AppendRow($statistics_html);
 		}
 	}
 
 	p_object.Refresh();
 }
 
 Debugger.prototype.errorCallback = function(p_req, p_pass, p_object) {
 	alert('AJAX ERROR: '+DebugReq.getErrorHtml(p_req));
 	p_object.Refresh();
 }
 
 Debugger.prototype.Refresh = function() {
 	// progress meter row
 
 	this.RemoveRow(0);
 	this.IsQueried = true;
 	this.DebuggerDIV.scrollTop = this.IsFatalError ? 10000000 : 0;
 	this.DebuggerDIV.scrollLeft = 0;
 }
 
 Debugger.prototype.Resize = function($e) {
 	if (!this.DebuggerDIV) return false;
 	var $pageTop = document.all ? document.body.offsetTop + document.body.scrollTop : window.scrollY;
 
 	this.DebuggerDIV.style.top = $pageTop + 'px';
 	this.DebuggerDIV.style.height = GetWindowHeight() + 'px';
 	return true;
 }
 
 function GetWindowHeight() {
 	var currWinHeight;
 
 //	if (document.body.clientHeight) {
 //		currWinHeight = document.body.clientHeight;
 
 	if (window.innerHeight) {//FireFox with correction for status bar at bottom of window
 		currWinHeight = window.innerHeight;
 	} else if (document.documentElement.clientHeight) {//IE 7 with correction for address bar
 		currWinHeight = document.documentElement.clientHeight;
 	} else if (document.body.offsetHeight) {//IE 4+
 		currWinHeight = document.body.offsetHeight + 10;
 	}
 	return currWinHeight - 10; // 10 - horizontal scrollbar height
 }
 
 
 /*function GetWinHeight() {
 	if (window.innerHeight) return window.innerHeight;
 	else if (document.documentElement.clientHeight) return document.documentElement.clientHeight;
 	else if (document.body.offsetHeight) return document.body.offsetHeight;
 	else return _winHeight;
 }*/
 
 Debugger.prototype.SetClipboard = function(copyText) {
 	if (window.clipboardData) {
 		// IE send-to-clipboard method.
 		window.clipboardData.setData('Text', copyText);
 	}
 	else if (window.netscape) {
 		// You have to sign the code to enable this or allow the action in about:config by changing user_pref("signed.applets.codebase_principal_support", true);
 		netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
 		// Store support string in an object.
 		var str = Components.classes['@mozilla.org/supports-string;1'].createInstance(Components.interfaces.nsISupportsString);
 		if (!str) {
 			return false;
 		}
 		str.data = copyText;
 
 		// Make transferable.
 		var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
 		if (!trans) {
 			return false;
 		}
 
 		// Specify what datatypes we want to obtain, which is text in this case.
 		trans.addDataFlavor('text/unicode');
 		trans.setTransferData('text/unicode', str, copyText.length * 2);
 
 		var clipid = Components.interfaces.nsIClipboard;
 		var clip = Components.classes['@mozilla.org/widget/clipboard;1'].getService(clipid);
 		if (!clip) {
 			return false;
 		}
 
 		clip.setData(trans, null, clipid.kGlobalClipboard);
 	}
 }
 
 Debugger.prototype.ShowProps = function($Obj, $Name) {
 	var $ret = '';
 	for ($Prop in $Obj) {
 		$ret += $Name + '.' + $Prop + ' = ' + $Obj[$Prop] + "\n";
 	}
 	return alert($ret);
 }
 
 Debugger.prototype.ToggleTraceArgs = function($arguments_layer_id) {
 	var $arguments_layer = document.getElementById($arguments_layer_id);
 	$arguments_layer.style.display = ($arguments_layer.style.display == 'none') ? 'block' : 'none';
 }
 
 Debugger.prototype.AddEvent = function (el, evname, func) {
 	var $status = false;
 	if (document.all) {
 		$status = el.attachEvent('on' + evname, func);
 	} else {
 		$status = el.addEventListener(evname, func, true);
 	}
 }
 
 Debugger.prototype.resetCache = function ($event_source) {
 	var $events = document.getElementById($event_source);
 	var $event = $events.options[$events.selectedIndex].value;
 
 	if (!$event) {
 		alert('Please select action to perform first!');
 	}
 	else if (confirm('Really perform "' + $events.options[$events.selectedIndex].innerHTML + '"?')) {
 		DebugReq.makeRequest(this.EventURL + '&' + $event, this.busyRequest, '', this.successCallback, this.errorCallback, 'resetCache', this);
 	}
 }
 
 Debugger.prototype.mouseCoords = function(ev)
 {
 	if(ev.pageX || ev.pageY){
 		var res = {x:ev.pageX, y:ev.pageY};
 	}
 	else {
 		var res = {
 			x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
 			y:ev.clientY + document.body.scrollTop  - document.body.clientTop
 		};
 	}
 	return res;
 }
 
 Debugger.prototype.MakeDragable = function(object_id, startCallback, moveCallback, endCallback, options)
 {
 	var drag_object = document.getElementById(object_id);
 	var cur_options = {'VerticalDrag': 1, 'HorizontalDrag': 1};
 	if (options) {
 		for(var i in options) {
 			cur_options[i] = options[i];
 		}
 	}
 	var the_debugger = this;
 	this.AddEvent(drag_object, 'mousedown', function(ev){
 		ev = ev || window.event;
 		the_debugger.InitialPos = dbg_findPos(drag_object);
 		var coords = the_debugger.mouseCoords(ev);
 		var pos = dbg_findPos(drag_object);
 		the_debugger.MouseOffset = [coords.x - pos[0], coords.y - pos[1]];
 		the_debugger.DragObject = drag_object;
 		the_debugger.LastDragObject = drag_object;
 		the_debugger.DragObject.style.position = 'absolute';
 		the_debugger.Options = cur_options;
 		startCallback(drag_object);
 	});
 	this.AddEvent(document, 'mousemove', function(ev) {
 //		window.status = 'mouse at: '+coords.x+','+coords.y;
 		if(the_debugger.DragObject){
 			ev = ev || window.event;
 			var coords = the_debugger.mouseCoords(ev);
 			if (the_debugger.Options.VerticalDrag) {
 				the_debugger.DragObject.style.top = (coords.y - the_debugger.MouseOffset[1] ) + 'px' // ;
 			}
 			if (the_debugger.Options.HorizontalDrag) {
 				the_debugger.DragObject.style.left = (coords.x - the_debugger.MouseOffset[0] ) + 'px' // ;
 			}
 			moveCallback(drag_object, coords)
 			return false;
 		}
 	});
 	this.AddEvent(document, 'mouseup', function(ev){
 		var tmp = the_debugger.DragObject;
 		the_debugger.DragObject = null;
 		if(tmp){
 			endCallback(tmp);
 		}
 		var pos = dbg_findPos(drag_object);
 	});
 }
 
 function dbg_findPos(obj) {
 	var curleft = curtop = 0;
 	if (obj.offsetParent) {
 		curleft = obj.offsetLeft
 		curtop = obj.offsetTop
 		while (obj = obj.offsetParent) {
 			curleft += obj.offsetLeft
 			curtop += obj.offsetTop
 		}
 	}
 	return [curleft,curtop];
 }
\ No newline at end of file
Index: branches/5.3.x/core/kernel/utility/debugger/debugger.css
===================================================================
--- branches/5.3.x/core/kernel/utility/debugger/debugger.css	(revision 15947)
+++ branches/5.3.x/core/kernel/utility/debugger/debugger.css	(revision 15948)
@@ -1,135 +1,137 @@
 #debug_layer code {
 	font-family: monospace;
 }
 
 #debug_layer b, #debug_layer strong {
 	font-weight: bold;
 }
 
 /* <br> tags inside <span> tags, produced by "hightlight_string" method call in PHP have strange bottom margin sometimes */
 
 .dbg_profiler {
 	margin-top: 5px;
 	padding: 0px;
 	height: 10px;
 	border: 1px solid #000000;
 	float: left;
 	display: inline;
 }
 
 .dbg_flat_table, .dbg_stats_table, table.dbg_explain_table {
 	border-collapse: collapse;
 	width: auto;
 	margin: 0px;
 }
 
 table.dbg_explain_table TD {
 	border: 1px solid #000000;
 	padding: 4px;
 }
 
 table.dbg_explain_table tr.explain_header TD {
 	font-weight: bold;
 	text-align: center;
 }
 
 .dbg_flat_table TD, .dbg_stats_table TD {
 	border: 1px solid #CCCCCC;
 	padding: 4px;
 }
 
 .dbg_stats_table TD {
 	background-color: #FFFFFF;
 	font-family: Arial, Verdana;
 	font-size: 9pt;
 	text-align: left;
 }
 
 .debug_cell .dbg_stats_table td {
 	background-color: transparent;
 }
 
 .debug_layer_table {
 	border-collapse: collapse;
 }
 
 .debug_text, .debug_row_even TD, .debug_row_odd TD {
 	color: #000000;
 	font-family: Verdana;
 	font-size: 11px;
 }
 
 .debug_cell {
 	border: 1px solid #FF0000;
 	padding: 4px;
 	text-align: left;
 }
 
 .debug_row_even {
 	background-color: #CCCCFF;
 }
 
 .debug_row_odd {
 	background-color: #FFFFCC;
 }
 
 .debug_layer_container {
 	left: 2px;
 	top: 1px;
 	z-index: 1500000;
 	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;
 }
 
 .debug_error {
 	color: #FF0000;
 }
 
 .dbg-toolbar {
 	border: 1px solid #000000;
 	background-color: #D4D0C8;
 	border-collapse: separate;
 	border-spacing: 2px;
 	width: auto;
 }
 
 .dbg-toolbar td {
 	font-size: 13px;
 	font-family: Tahoma;
 	padding: 1px 5px 1px 5px;
 	vertical-align: middle;
 	margin: 3px;
 }
 
 .dbg-toolbar td.dbg-button, .dbg-toolbar td.dbg-button:hover {
 	cursor: default;
 }
 
 .dbg-toolbar td.dbg-button {
 	border: 1px solid #D4D0C8;
 	background-color: #D4D0C8;
 }
 
 .dbg-toolbar td.dbg-button:hover {
 	border: 1px solid #0A246A;
 	background-color: #B5BDD2;
 }
 
 .dbg-toolbar td.dbg-separator {
 	background-color: #000000;
 	width: 1px;
 	padding: 0px;
 }
 
-
+.dbg-error-row-hidden tr[data-row-type="error"], .dbg-warning-row-hidden tr[data-row-type="warning"],
+.dbg-notice-row-hidden tr[data-row-type="notice"], .dbg-sql-row-hidden tr[data-row-type="sql"],
+.dbg-other-row-hidden tr[data-row-type="other"] {display: none}
\ No newline at end of file
Index: branches/5.3.x/core/kernel/utility/debugger.php
===================================================================
--- branches/5.3.x/core/kernel/utility/debugger.php	(revision 15947)
+++ branches/5.3.x/core/kernel/utility/debugger.php	(revision 15948)
@@ -1,1986 +1,2055 @@
 <?php
 /**
 * @version	$Id$
 * @package	In-Portal
 * @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
 * @license      GNU/GPL
 * In-Portal is Open Source software.
 * This means that this software may have been modified pursuant
 * the GNU General Public License, and as distributed it includes
 * or is derivative of works licensed under the GNU General Public License
 * or other free or open source software licenses.
 * See http://www.in-portal.org/license for copyright notices and details.
 */
 
 	defined('FULL_PATH') or die('restricted access!');
 
 	if( !class_exists('Debugger') ) {
 
 		/**
 		 * Contains misc functions, used by debugger (mostly copied from kUtil class)
 		 */
 		class DebuggerUtil {
 
 			/**
 			 * Trust information, provided by proxy
 			 *
 			 * @var bool
 			 */
 			public static $trustProxy = false;
 
 			/**
 			 * Checks if constant is defined and has positive value
 			 *
 			 * @param string $const_name
 			 * @return bool
 			 */
 			public static function constOn($const_name)
 			{
 				return defined($const_name) && constant($const_name);
 			}
 
 			/**
 			 * Define constant if it was not already defined before
 			 *
 			 * @param string $const_name
 			 * @param string $const_value
 			 * @access public
 			 */
 			public static function safeDefine($const_name, $const_value)
 			{
 				if ( !defined($const_name) ) {
 					define($const_name, $const_value);
 				}
 			}
 
 			/**
 			 * Formats file/memory size in nice way
 			 *
 			 * @param int $bytes
 			 * @return string
 			 * @access public
 			 */
 			public static function formatSize($bytes)
 			{
 				if ($bytes >= 1099511627776) {
 					$return = round($bytes / 1024 / 1024 / 1024 / 1024, 2);
 					$suffix = "TB";
 				} elseif ($bytes >= 1073741824) {
 					$return = round($bytes / 1024 / 1024 / 1024, 2);
 					$suffix = "GB";
 				} elseif ($bytes >= 1048576) {
 					$return = round($bytes / 1024 / 1024, 2);
 					$suffix = "MB";
 				} elseif ($bytes >= 1024) {
 					$return = round($bytes / 1024, 2);
 					$suffix = "KB";
 				} else {
 					$return = $bytes;
 					$suffix = "Byte";
 				}
 
 				$return .= ' '.$suffix;
 
 				return $return;
 			}
 
 			/**
 			 * Checks, that user IP address is within allowed range
 			 *
 			 * @param string $ip_list semi-column (by default) separated ip address list
 			 * @param string $separator ip address separator (default ";")
 			 *
 			 * @return bool
 			 */
 			public static function ipMatch($ip_list, $separator = ';')
 			{
 				if ( php_sapi_name() == 'cli' ) {
 					return false;
 				}
 
 				$ip_match = false;
 				$ip_addresses = $ip_list ? explode($separator, $ip_list) : Array ();
 				$client_ip = self::getClientIp();
 
 				foreach ($ip_addresses as $ip_address) {
 					if ( self::netMatch($ip_address, $client_ip) ) {
 						$ip_match = true;
 						break;
 					}
 				}
 
 				return $ip_match;
 			}
 
 			/**
 			 * Returns the client IP address.
 			 *
 			 * @return string The client IP address
 			 * @access public
 			 */
 			public static function getClientIp()
 			{
 				if ( self::$trustProxy ) {
 					if ( array_key_exists('HTTP_CLIENT_IP', $_SERVER) ) {
 						return $_SERVER['HTTP_CLIENT_IP'];
 					}
 
 					if ( array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER) ) {
 						$client_ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
 
 						foreach ($client_ip as $ip_address) {
 							$clean_ip_address = trim($ip_address);
 
 							if ( false !== filter_var($clean_ip_address, FILTER_VALIDATE_IP) ) {
 								return $clean_ip_address;
 							}
 						}
 
 						return '';
 					}
 				}
 
 				return $_SERVER['REMOTE_ADDR'];
 			}
 
 			/**
 			 * Checks, that given ip belongs to given subnet
 			 *
 			 * @param string $network
 			 * @param string $ip
 			 * @return bool
 			 * @access public
 			 */
 			public static function netMatch($network, $ip) {
 
 				$network = trim($network);
 				$ip = trim($ip);
 
 				if ( preg_replace('/[\d\.\/-]/', '', $network) != '' ) {
 					$network = gethostbyname($network);
 				}
 
 				if ($network == $ip) {
 					// comparing two ip addresses directly
 					return true;
 				}
 
 				$d = strpos($network, '-');
 				if ($d !== false) {
 					// ip address range specified
 					$from = ip2long(trim(substr($network, 0, $d)));
 					$to = ip2long(trim(substr($network, $d + 1)));
 
 					$ip = ip2long($ip);
 					return ($ip >= $from && $ip <= $to);
 				}
 				elseif (strpos($network, '/') !== false) {
 					// single subnet specified
 					$ip_arr = explode('/', $network);
 
 					if (!preg_match("@\d*\.\d*\.\d*\.\d*@", $ip_arr[0], $matches)) {
 						$ip_arr[0] .= '.0';    // Alternate form 194.1.4/24
 					}
 
 					$network_long = ip2long($ip_arr[0]);
 					$x = ip2long($ip_arr[1]);
 
 					$mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1]));
 					$ip_long = ip2long($ip);
 
 					return ($ip_long & $mask) == ($network_long & $mask);
 				}
 
 				return false;
 			}
 		}
 
 		/**
 		 * Main debugger class, that can be used with any In-Portal (or not) project
 		 */
 		class Debugger {
 
+			const ROW_TYPE_ERROR = 'error';
+
+			const ROW_TYPE_WARNING = 'warning';
+
+			const ROW_TYPE_NOTICE = 'notice';
+
+			const ROW_TYPE_SQL = 'sql';
+
+			const ROW_TYPE_OTHER = 'other';
+
 			/**
 			 * Holds reference to global KernelApplication instance
 			 *
 			 * @var kApplication
 			 * @access private
 			 */
 			private $Application = null;
 
 			/**
 			 * Set to true if fatal error occurred
 			 *
 			 * @var bool
 			 * @access private
 			 */
 			private $IsFatalError = false;
 
 			/**
 			 * Tells if last error (if any) caught by shutdown function  was processed
 			 *
 			 * @var bool
 			 * @access private
 			 */
 			private $_lastErrorProcessed = false;
 
+			private $_filterTypes = Array ('error', 'warning', 'notice', 'sql', 'other');
+
 			/**
 			 * Counts warnings on the page
 			 *
 			 * @var int
 			 * @access public
 			 */
 			public $WarningCount = 0;
 
 			/**
 			 * Allows to track compile errors, like "stack-overflow"
 			 *
 			 * @var bool
 			 * @access private
 			 */
 			private $_compileError = false;
 
 			/**
 			 * Debugger data for building report
 			 *
 			 * @var Array
 			 * @access private
 			 */
 			private $Data = Array ();
 
 			/**
 			 * Holds information about each profiler record (start/end/description)
 			 *
 			 * @var Array
 			 * @access private
 			 */
 			private $ProfilerData = Array ();
 
 			/**
 			 * Holds information about total execution time per profiler key (e.g. total sql time)
 			 *
 			 * @var Array
 			 * @access private
 			 */
 			private $ProfilerTotals = Array ();
 
 			/**
 			 * Counts how much each of total types were called (e.g. total error count)
 			 *
 			 * @var Array
 			 * @access private
 			 */
 			private $ProfilerTotalCount = Array ();
 
 			/**
 			 * Holds information about all profile points registered
 			 *
 			 * @var Array
 			 * @access private
 			 */
 			private $ProfilePoints = Array ();
 
 			/**
 			 * Prevent recursion when processing debug_backtrace() function results
 			 *
 			 * @var Array
 			 * @access private
 			 */
 			private $RecursionStack = Array ();
 
 			/**
 			 * Cross browser debugger report scrollbar width detection
 			 *
 			 * @var int
 			 * @access private
 			 */
 			private $scrollbarWidth = 0;
 
 			/**
 			 * Remembers how much memory & time was spent on including files
 			 *
 			 * @var Array
 			 * @access public
 			 * @see kUtil::includeOnce
 			 */
 			public $IncludesData = Array ();
 
 			/**
 			 * Remembers maximal include deep level
 			 *
 			 * @var int
 			 * @access public
 			 * @see kUtil::includeOnce
 			 */
 			public $IncludeLevel = 0;
 
 			/**
 			 * Prevents report generation more then once
 			 *
 			 * @var bool
 			 * @access private
 			 */
 			private $reportDone = false;
 
 			/**
 			 * Transparent spacer image used in case of none spacer image defined via SPACER_URL constant.
 			 * Used while drawing progress bars (memory usage, time usage, etc.)
 			 *
 			 * @var string
 			 * @access private
 			 */
 			private $dummyImage = '';
 
 			/**
 			 * Temporary files created by debugger will be stored here
 			 *
 			 * @var string
 			 * @access private
 			 */
 			private $tempFolder = '';
 
 			/**
 			 * Debug rows will be separated using this string before writing to debug file
 			 *
 			 * @var string
 			 * @access private
 			 */
 			private $rowSeparator = '@@';
 
 			/**
 			 * Base URL for debugger includes
 			 *
 			 * @var string
 			 * @access private
 			 */
 			private $baseURL = '';
 
 			/**
 			 * Sub-folder, where In-Portal is installed
 			 *
 			 * @var string
 			 * @access private
 			 */
 			private $basePath = '';
 
 			/**
 			 * Holds last recorded timestamp (for appendTimestamp)
 			 *
 			 * @var int
 			 * @access private
 			 */
 			private $LastMoment;
 
 			/**
 			 * Determines, that current request is AJAX request
 			 *
 			 * @var bool
 			 * @access private
 			 */
 			private $_isAjax = false;
 
 			/**
 			 * Creates instance of debugger
 			 */
 			public function __construct()
 			{
 				global $start, $dbg_options;
 
 				// check if user haven't defined DEBUG_MODE contant directly
 				if ( defined('DEBUG_MODE') && DEBUG_MODE ) {
 					die('error: constant DEBUG_MODE defined directly, please use <strong>$dbg_options</strong> array instead');
 				}
 
 				if ( class_exists('kUtil') ) {
 					$vars = kUtil::getConfigVars();
 					DebuggerUtil::$trustProxy = isset($vars['TrustProxy']) ? (bool)$vars['TrustProxy'] : false;
 				}
 
 				// check IP before enabling debug mode
 				$ip_match = DebuggerUtil::ipMatch(isset($dbg_options['DBG_IP']) ? $dbg_options['DBG_IP'] : '');
 
 				if ( !$ip_match || (isset($_COOKIE['debug_off']) && $_COOKIE['debug_off']) ) {
 					define('DEBUG_MODE', 0);
 					return;
 				}
 
 				// debug is allowed for user, continue initialization
 				$this->InitDebugger();
 				$this->profileStart('kernel4_startup', 'Startup and Initialization of kernel4', $start);
 				$this->profileStart('script_runtime', 'Script runtime', $start);
 				$this->LastMoment = $start;
 
 				error_reporting(E_ALL & ~E_STRICT);
 
 				// show errors on screen in case if not in Zend Studio debugging
 				ini_set('display_errors', DebuggerUtil::constOn('DBG_ZEND_PRESENT') ? 0 : 1);
 
 				// vertical scrollbar width differs in Firefox and other browsers
 				$this->scrollbarWidth = $this->isGecko() ? 22 : 25;
 
 				$this->appendRequest();
 			}
 
 			/**
 			 * Set's default values to constants debugger uses
 			 *
 			 */
 			function InitDebugger()
 			{
 				global $dbg_options;
 
 				unset($dbg_options['DBG_IP']);
 
 				// Detect fact, that this session being debugged by Zend Studio
 				foreach ($_COOKIE as $cookie_name => $cookie_value) {
 					if (substr($cookie_name, 0, 6) == 'debug_') {
 						DebuggerUtil::safeDefine('DBG_ZEND_PRESENT', 1);
 						break;
 					}
 				}
 
 				DebuggerUtil::safeDefine('DBG_ZEND_PRESENT', 0); // set this constant value to 0 (zero) to debug debugger using Zend Studio
 
 				// set default values for debugger constants
 				$dbg_constMap = Array (
 					'DBG_USE_HIGHLIGHT'			=>	1,							// highlight output same as php code using "highlight_string" function
 					'DBG_WINDOW_WIDTH'			=>	700,						// set width of debugger window (in pixels) for better viewing large amount of debug data
 					'DBG_USE_SHUTDOWN_FUNC'		=>	DBG_ZEND_PRESENT ? 0 : 1,	// use shutdown function to include debugger code into output
 					'DBG_HANDLE_ERRORS'			=>	DBG_ZEND_PRESENT ? 0 : 1,	// handle all allowed by php (see php manual) errors instead of default handler
 					'DBG_DOMVIEWER'				=>	'/temp/domviewer.html',		// path to DOMViewer on website
 					'DOC_ROOT'					=>	str_replace('\\', '/', realpath($_SERVER['DOCUMENT_ROOT']) ), // windows hack
 					'DBG_LOCAL_BASE_PATH'		=>	'w:',						// replace DOC_ROOT in filenames (in errors) using this path
 					'DBG_EDITOR_URL'			=>	'file://%F:%L',
 					'DBG_SHORTCUT'				=>	'F12',						// Defines debugger activation shortcut (any symbols or Ctrl/Alt/Shift are allowed, e.g. Ctrl+Alt+F12)
 				);
 
 				// debugger is initialized before kHTTPQuery, so do jQuery headers check here too
 				if (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {
 					$this->_isAjax = true;
 				}
 				elseif (array_key_exists('ajax', $_GET) && $_GET['ajax'] == 'yes') {
 					$this->_isAjax = true;
 				}
 
 				// user defined options override debugger defaults
 				$dbg_constMap = array_merge($dbg_constMap, $dbg_options);
 
 				if ($this->_isAjax && array_key_exists('DBG_SKIP_AJAX', $dbg_constMap) && $dbg_constMap['DBG_SKIP_AJAX']) {
 					$dbg_constMap['DBG_SKIP_REPORTING'] = 1;
 				}
 
 				// allows to validate unit configs via request variable
 				if ( !array_key_exists('DBG_VALIDATE_CONFIGS', $dbg_constMap) ) {
 					$dbg_constMap['DBG_VALIDATE_CONFIGS'] = array_key_exists('validate_configs', $_GET) ? (int)$_GET['validate_configs'] : 0;
 				}
 
 				// when validation configs, don't show sqls for better validation error displaying
 				if ($dbg_constMap['DBG_VALIDATE_CONFIGS']) {
 					$dbg_constMap['DBG_SQL_PROFILE'] = 0;
 				}
 
 				// when showing explain make shure, that debugger window is large enough
 				if (array_key_exists('DBG_SQL_EXPLAIN', $dbg_constMap) && $dbg_constMap['DBG_SQL_EXPLAIN']) {
 					$dbg_constMap['DBG_WINDOW_WIDTH'] = 1000;
 				}
 
 				foreach ($dbg_constMap as $dbg_constName => $dbg_constValue) {
 					DebuggerUtil::safeDefine($dbg_constName, $dbg_constValue);
 				}
 			}
 
 			/**
 			 * Performs debugger initialization
 			 *
 			 * @return void
 			 */
 			private function InitReport()
 			{
 				if ( !class_exists('kApplication') ) {
 					return;
 				}
 
 				$application =& kApplication::Instance();
 
 				// string used to separate debugger records while in file (used in debugger dump filename too)
 				$this->rowSeparator = '@' . (/*is_object($application->Factory) &&*/ $application->InitDone ? $application->GetSID() : 0) . '@';
 //				$this->rowSeparator = '@' . rand(0, 100000) . '@';
 
 				// include debugger files from this url
 				$reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/';
 				$kernel_path = preg_replace($reg_exp, '', KERNEL_PATH, 1);
 				$this->baseURL = PROTOCOL . SERVER_NAME . (defined('PORT') ? ':' . PORT : '') . rtrim(BASE_PATH, '/') . $kernel_path . '/utility/debugger';
 
 				// store debugger cookies at this path
 				$this->basePath = rtrim(BASE_PATH, '/');
 
 				// save debug output in this folder
 				$this->tempFolder = defined('RESTRICTED') ? RESTRICTED : WRITEABLE . '/cache';
 			}
 
 			/**
 			 * Appends all passed variable values (without variable names) to debug output
 			 *
 			 * @return void
 			 * @access public
 			 */
 			public function dumpVars()
 			{
 				$dump_mode = 'var_dump';
 				$dumpVars = func_get_args();
 
 				if ( $dumpVars[count($dumpVars) - 1] === 'STRICT' ) {
 					$dump_mode = 'strict_var_dump';
 					array_pop($dumpVars);
 				}
 
 				foreach ($dumpVars as $varValue) {
 					$this->Data[] = Array ('value' => $varValue, 'debug_type' => $dump_mode);
 				}
 			}
 
 			/**
 			 * Transforms collected data at given index into human-readable HTML to place in debugger report
 			 *
 			 * @param int $dataIndex
 			 * @return string
 			 * @access private
 			 */
 			private function prepareHTML($dataIndex)
 			{
 				static $errors_displayed = 0;
 
 				$Data =& $this->Data[$dataIndex];
 				if ( $Data['debug_type'] == 'html' ) {
 					return $Data['html'];
 				}
 
 				switch ($Data['debug_type']) {
 					case 'error':
 						$errors_displayed++;
 						$fileLink = $this->getFileLink($Data['file'], $Data['line']);
 						$ret = '<b class="debug_error">' . $this->getErrorNameByCode($Data['no']) . ' (#' . $errors_displayed . ')</b>: ' . $Data['str'];
 						$ret .= ' in <b>' . $fileLink . '</b> on line <b>' . $Data['line'] . '</b>';
 						return $ret;
 						break;
 
 					case 'exception':
 						$fileLink = $this->getFileLink($Data['file'], $Data['line']);
 						$ret = '<b class="debug_error">' . $Data['exception_class'] . '</b>: ' . $Data['str'];
 						$ret .= ' in <b>' . $fileLink . '</b> on line <b>' . $Data['line'] . '</b>';
 						return $ret;
 						break;
 
 					case 'var_dump':
 						return $this->highlightString($this->print_r($Data['value'], true));
 						break;
 
 					case 'strict_var_dump':
 						return $this->highlightString(var_export($Data['value'], true));
 						break;
 
 					case 'trace':
 						ini_set('memory_limit', '500M');
 						$trace =& $Data['trace'];
 
 						$i = 0;
 						$traceCount = count($trace);
 						$ret = '';
 
 						while ( $i < $traceCount ) {
 							$traceRec =& $trace[$i];
 							$argsID = 'trace_args_' . $dataIndex . '_' . $i;
 
 							$has_args = isset($traceRec['args']);
 
 							if ( isset($traceRec['file']) ) {
 								$func_name = isset($traceRec['class']) ? $traceRec['class'] . $traceRec['type'] . $traceRec['function'] : $traceRec['function'];
 								$args_link = $has_args ? '<a href="javascript:$Debugger.ToggleTraceArgs(\'' . $argsID . '\');" title="Show/Hide Function Arguments"><b>Function</b></a>' : '<strong>Function</strong>';
 
 								$ret .= $args_link . ': ' . $this->getFileLink($traceRec['file'], $traceRec['line'], $func_name);
 								$ret .= ' in <b>' . basename($traceRec['file']) . '</b> on line <b>' . $traceRec['line'] . '</b><br>';
 							}
 							else {
 								$ret .= 'no file information available';
 							}
 
 							if ( $has_args ) {
 								// if parameter value is longer then 200 symbols, then leave only first 50
 								$args = $this->highlightString($this->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
 
 						$totals_key = getArrayValue($Data, 'totalsKey');
 						if ( $totals_key ) {
 							$total_before = $Data['totalsBefore'];
 							$total = $this->ProfilerTotals[$totals_key];
 
 							$div_width = Array ();
 							$total_width = ($this->getWindowWidth() - 10);
 							$div_width['before'] = round(($total_before / $total) * $total_width);
 							$div_width['current'] = round(($runtime / $total) * $total_width);
 							$div_width['left'] = round((($total - $total_before - $runtime) / $total) * $total_width);
 
 							$subtitle = array_key_exists('subtitle', $Data) ? ' (' . $Data['subtitle'] . ')' : '';
 							$ret = '<b>Name' . $subtitle . '</b>: ' . $Data['description'] . '<br />';
 
 							$additional = isset($Data['additional']) ? $Data['additional'] : Array ();
 							if ( isset($Data['file']) ) {
 								array_unshift($additional, Array ('name' => 'File', 'value' => $this->getFileLink($Data['file'], $Data['line'], basename($Data['file']) . ':' . $Data['line'])));
 							}
 							array_unshift($additional, Array ('name' => 'Runtime', 'value' => $runtime . 's'));
 
 							$ret .= '<div>'; //FF 3.5 needs this!
 							foreach ($additional as $mixed_param) {
 								$ret .= '[<strong>' . $mixed_param['name'] . '</strong>: ' . $mixed_param['value'] . '] ';
 							}
 
 							/*if ( isset($Data['file']) ) {
 								$ret .= '[<b>Runtime</b>: ' . $runtime . 's] [<b>File</b>: ' . $this->getFileLink($Data['file'], $Data['line'], basename($Data['file']) . ':' . $Data['line']) . ']<br />';
 							}
 							else {
 								$ret .= '<b>Runtime</b>: ' . $runtime . 's<br />';
 							}*/
 
 							$ret .= '</div>';
 
 							$ret .= '<div class="dbg_profiler" style="width: ' . $div_width['before'] . 'px; border-right: 0px; background-color: #298DDF;"><img src="' . $this->dummyImage . '" width="1" height="1"/></div>';
 							$ret .= '<div class="dbg_profiler" style="width: ' . $div_width['current'] . 'px; border-left: 0px; border-right: 0px; background-color: #EF4A4A;"><img src="' . $this->dummyImage . '" width="1" height="1"/></div>';
 							$ret .= '<div class="dbg_profiler" style="width: ' . $div_width['left'] . 'px; border-left: 0px; background-color: #DFDFDF;"><img src="' . $this->dummyImage . '" width="1" height="1"/></div>';
 
 							return $ret;
 						}
 						else {
 							return '<b>Name</b>: ' . $Data['description'] . '<br><b>Runtime</b>: ' . $runtime . 's';
 						}
 						break;
 
 					default:
 						return 'incorrect debug data';
 						break;
 				}
 			}
 
 			/**
+			 * Returns row type for debugger row.
+			 *
+			 * @param integer $data_index Index of the row.
+			 *
+			 * @return string
+			 */
+			protected function getRowType($data_index)
+			{
+				$data = $this->Data[$data_index];
+
+				switch ($data['debug_type']) {
+					case 'html':
+						if ( strpos($data['html'], 'SQL Total time') !== false ) {
+							return self::ROW_TYPE_SQL;
+						}
+						break;
+
+					case 'error':
+						$error_map = array(
+							'Fatal Error' => self::ROW_TYPE_ERROR,
+							'Warning' => self::ROW_TYPE_WARNING,
+							'Notice' => self::ROW_TYPE_NOTICE,
+						);
+
+						return $error_map[$this->getErrorNameByCode($data['no'])];
+						break;
+
+					case 'exception':
+						return self::ROW_TYPE_ERROR;
+						break;
+
+					case 'profiler':
+						if ( preg_match('/^sql_/', $data['profile_key']) ) {
+							return self::ROW_TYPE_SQL;
+						}
+						break;
+				}
+
+				return self::ROW_TYPE_OTHER;
+			}
+
+			/**
 			 * Returns debugger report window width excluding scrollbar
 			 *
 			 * @return int
 			 * @access private
 			 */
 			private function getWindowWidth()
 			{
 				return DBG_WINDOW_WIDTH - $this->scrollbarWidth - 8;
 			}
 
 			/**
 			 * Tells debugger to skip objects that are heavy in plan of memory usage while printing debug_backtrace results
 			 *
 			 * @param Object $object
 			 * @return bool
 			 * @access private
 			 */
 			private function IsBigObject(&$object)
 			{
 				$skip_classes = Array(
 					defined('APPLICATION_CLASS') ? APPLICATION_CLASS : 'kApplication',
 					'kFactory',
 					'kUnitConfigReader',
 					'NParser',
 				);
 
 				foreach ($skip_classes as $class_name) {
 					if ( strtolower(get_class($object)) == strtolower($class_name) ) {
 						return true;
 					}
 				}
 
 				return false;
 			}
 
 			/**
 			 * Advanced version of print_r (for debugger only). Don't print objects recursively
 			 *
 			 * @param Array $array
 			 * @param bool $return_output return output or print it out
 			 * @param int $tab_count offset in tabs
 			 * @return string
 			 * @access private
 			 */
 			private function print_r(&$array, $return_output = false, $tab_count = -1)
 			{
 				static $first_line = true;
 
 				// not an array at all
 				if ( !is_array($array) ) {
 					switch ( gettype($array) ) {
 						case 'NULL':
 							return 'NULL' . "\n";
 							break;
 
 						case 'object':
 							return $this->processObject($array, $tab_count);
 							break;
 
 						default:
 							// number or string
 							if ( strlen($array) > 200 ) {
 								$array = substr($array, 0, 50) . ' ...';
 							}
 							return $array . "\n";
 							break;
 					}
 				}
 
 				$output = '';
 
 				$tab_count++;
 				$output .= "Array\n" . str_repeat('    ', $tab_count) . "(\n";
 
 				$tab_count++;
 				$tabsign = $tab_count ? str_repeat('    ', $tab_count) : '';
 
 				$array_keys = array_keys($array);
 
 				foreach ($array_keys as $key) {
 					switch ( gettype($array[$key]) ) {
 						case 'array':
 							$output .= $tabsign . '[' . $key . '] = ' . $this->print_r($array[$key], true, $tab_count);
 							break;
 
 						case 'boolean':
 							$output .= $tabsign . '[' . $key . '] = ' . ($array[$key] ? 'true' : 'false') . "\n";
 							break;
 
 						case 'integer':
 						case 'double':
 						case 'string':
 							if ( strlen($array[$key]) > 200 ) {
 								$array[$key] = substr($array[$key], 0, 50) . ' ...';
 							}
 							$output .= $tabsign . '[' . $key . '] = ' . $array[$key] . "\n";
 							break;
 
 						case 'NULL':
 							$output .= $tabsign . '[' . $key . "] = NULL\n";
 							break;
 
 						case 'object':
 							$output .= $tabsign . '[' . $key . "] = ";
 							$output .= "Object (" . get_class($array[$key]) . ") = \n" . str_repeat('    ', $tab_count + 1) . "(\n";
 							$output .= $this->processObject($array[$key], $tab_count + 2);
 							$output .= str_repeat('    ', $tab_count + 1) . ")\n";
 							break;
 
 						default:
 							$output .= $tabsign . '[' . $key . '] unknown = ' . gettype($array[$key]) . "\n";
 							break;
 					}
 				}
 
 				$tab_count--;
 				$output .= str_repeat('    ', $tab_count) . ")\n";
 
 				if ( $first_line ) {
 					$first_line = false;
 					$output .= "\n";
 				}
 
 				$tab_count--;
 
 				if ( $return_output ) {
 					return $output;
 				}
 				else {
 					echo $output;
 				}
 
 				return true;
 			}
 
 			/**
 			 * Returns string representation of given object (more like print_r, but with recursion prevention check)
 			 *
 			 * @param Object $object
 			 * @param int $tab_count
 			 * @return string
 			 * @access private
 			 */
 			private function processObject(&$object, $tab_count)
 			{
 				$object_class = get_class($object);
 				if ( !in_array($object_class, $this->RecursionStack) ) {
 					if ( $this->IsBigObject($object) ) {
 						return 'SKIPPED (class: ' . $object_class . ")\n";
 					}
 
 					$attribute_names = get_class_vars($object_class);
 					if ( !$attribute_names ) {
 						return "NO_ATTRIBUTES\n";
 					}
 					else {
 						$output = '';
 						array_push($this->RecursionStack, $object_class);
 
 						$tabsign = $tab_count ? str_repeat('    ', $tab_count) : '';
 						foreach ($attribute_names as $attribute_name => $attribute_value) {
 							if ( is_object($object->$attribute_name) ) {
 								// it is object
 								$output .= $tabsign . '[' . $attribute_name . '] = ' . $this->processObject($object->$attribute_name, $tab_count + 1);
 							}
 							else {
 								$output .= $tabsign . '[' . $attribute_name . '] = ' . $this->print_r($object->$attribute_name, true, $tab_count);
 							}
 						}
 						array_pop($this->RecursionStack);
 						return $output;
 					}
 				}
 				else {
 					// object [in recursion stack]
 					return '*** RECURSION *** (class: ' . $object_class . ")\n";
 				}
 			}
 
 			/**
 			 * Format SQL Query using predefined formatting
 			 * and highlighting techniques
 			 *
 			 * @param string $sql
 			 * @return string
 			 * @access public
 			 */
 			public function formatSQL($sql)
 			{
 				$sql = trim(preg_replace('/(\n|\t| )+/is', ' ', $sql));
 
 				// whitespace in the beginning of the regex is to avoid splitting inside words, for example "FROM int_ConfigurationValues" into "FROM intConfiguration\n\tValues"
 				$formatted_sql = preg_replace('/\s(CREATE TABLE|DROP TABLE|SELECT|UPDATE|SET|REPLACE|INSERT|DELETE|VALUES|FROM|LEFT JOIN|INNER JOIN|LIMIT|WHERE|HAVING|GROUP BY|ORDER BY)\s/is', "\n\t$1 ", ' ' . $sql);
 				$formatted_sql = $this->highlightString($formatted_sql);
 
 				if ( defined('DBG_SQL_EXPLAIN') && DBG_SQL_EXPLAIN ) {
 					if ( substr($sql, 0, 6) == 'SELECT' ) {
 						$formatted_sql .= '<br/>' . '<strong>Explain</strong>:<br /><br />';
 						$explain_result = $this->Application->Conn->Query('EXPLAIN ' . $sql, null, true);
 
 						$explain_table = '';
 						foreach ($explain_result as $explain_row) {
 							if ( !$explain_table ) {
 								// first row -> draw header
 								$explain_table .= '<tr class="explain_header"><td>' . implode('</td><td>', array_keys($explain_row)) . '</td></tr>';
 							}
 							$explain_table .= '<tr><td>' . implode('</td><td>', $explain_row) . '</td></tr>';
 						}
 
 						$formatted_sql .= '<table class="dbg_explain_table">' . $explain_table . '</table>';
 					}
 				}
 
 				return $formatted_sql;
 			}
 
 			/**
 			 * Highlights given string using "highlight_string" method
 			 *
 			 * @param string $string
 			 * @return string
 			 * @access public
 			 */
 			public function highlightString($string)
 			{
 				if ( !(defined('DBG_USE_HIGHLIGHT') && DBG_USE_HIGHLIGHT) || $this->_compileError ) {
 					return nl2br($string);
 				}
 
 				$string = str_replace(Array ('\\', '/'), Array ('_no_match_string_', '_n_m_s_'), $string);
 				$this->_compileError = true; // next line is possible cause of compile error
 				$string = highlight_string('<?php ' . $string . ' ?>', true);
 				$this->_compileError = false;
 
 				$string = str_replace(Array ('_no_match_string_', '_n_m_s_'), Array ('\\', '/'), $string);
 
 				if ( strlen($string) >= 65536 ) {
 					// preg_replace will fail, when string is longer, then 65KB
 					return str_replace(Array ('&lt;?php&nbsp;', '?&gt;'), '', $string);
 				}
 
 				return preg_replace('/&lt;\?(.*)php&nbsp;(.*)\?&gt;/Us', '\\2', $string);
 			}
 
 			/**
 			 * Determine by php type of browser used to show debugger
 			 *
 			 * @return bool
 			 * @access private
 			 */
 			private function isGecko()
 			{
 				// we need isset because we may run scripts from shell with no user_agent at all
 				return isset($_SERVER['HTTP_USER_AGENT']) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'firefox') !== false;
 			}
 
 			/**
 			 * Returns link for editing php file (from error) in external editor
 			 *
 			 * @param string $file filename with path from root folder
 			 * @param int $line_number line number in file where error is found
 			 * @param string $title text to show on file edit link
 			 * @return string
 			 * @access public
 			 */
 			public function getFileLink($file, $line_number = 1, $title = '')
 			{
 				if ( !$title ) {
 					$title = str_replace('/', '\\', $this->getLocalFile($file));
 				}
 
 				$url = str_replace('%F', $this->getLocalFile($file), DBG_EDITOR_URL);
 				$url = str_replace('%L', $line_number, $url);
 
 				return '<a href="' . $url . '">' . $title . '</a>';
 			}
 
 			/**
 			 * Converts filepath on server to filepath in mapped DocumentRoot on developer pc
 			 *
 			 * @param string $remoteFile
 			 * @return string
 			 * @access private
 			 */
 			private function getLocalFile($remoteFile)
 			{
 				return preg_replace('/^' . preg_quote(DOC_ROOT, '/') . '/', DBG_LOCAL_BASE_PATH, $remoteFile, 1);
 			}
 
 			/**
 			 * Appends call trace till this method call
 			 *
 			 * @param int $levels_to_shift
 			 * @return void
 			 * @access public
 			 */
 			public function appendTrace($levels_to_shift = 1)
 			{
 				$levels_shifted = 0;
 				$trace = debug_backtrace();
 
 				while ( $levels_shifted < $levels_to_shift ) {
 					array_shift($trace);
 					$levels_shifted++;
 				}
 
 				$this->Data[] = Array ('trace' => $trace, 'debug_type' => 'trace');
 			}
 
 			/**
 			 * Appends call trace till this method call
 			 *
 			 * @param Exception $exception
 			 * @return void
 			 * @access private
 			 */
 			private function appendExceptionTrace(&$exception)
 			{
 				$trace = $exception->getTrace();
 				$this->Data[] = Array('trace' => $trace, 'debug_type' => 'trace');
 			}
 
 			/**
 			 * Adds memory usage statistics
 			 *
 			 * @param string $msg
 			 * @param int $used
 			 * @return void
 			 * @access public
 			 */
 			public function appendMemoryUsage($msg, $used = null)
 			{
 				if ( !isset($used) ) {
 					$used = round(memory_get_usage() / 1024);
 				}
 
 				$this->appendHTML('<b>Memory usage</b> ' . $msg . ' ' . $used . 'Kb');
 			}
 
 			/**
 			 * Appends HTML code without transformations
 			 *
 			 * @param string $html
 			 * @return void
 			 * @access public
 			 */
 			public function appendHTML($html)
 			{
 				$this->Data[] = Array ('html' => $html, 'debug_type' => 'html');
 			}
 
 			/**
 			 * Returns instance of FirePHP class
 			 *
 			 * @return FirePHP
 			 * @link http://www.firephp.org/HQ/Use.htm
 			 */
 			function firePHP()
 			{
 				require_once('FirePHPCore/FirePHP.class.php');
 
 				return FirePHP::getInstance(true);
 			}
 
 			/**
 			 * 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
 			 * @access public
 			 */
 			public 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
 			 * @return void
 			 * @access private
 			 */
 			private function moveToBegin($debugLineCount)
 			{
 				$lines = array_splice($this->Data, count($this->Data) - $debugLineCount, $debugLineCount);
 				$this->Data = array_merge($lines, $this->Data);
 			}
 
 			/**
 			 * Moves all debugger report lines after $debugLineCount into $new_row position
 			 *
 			 * @param int $new_row
 			 * @param int $debugLineCount
 			 * @return void
 			 * @access private
 			 */
 			private function moveAfterRow($new_row, $debugLineCount)
 			{
 				$lines = array_splice($this->Data, count($this->Data) - $debugLineCount, $debugLineCount);
 				$rows_before = array_splice($this->Data, 0, $new_row, $lines);
 				$this->Data = array_merge($rows_before, $this->Data);
 			}
 
 			/**
 			 * Appends HTTP REQUEST information to debugger report
 			 *
 			 * @return void
 			 * @access private
 			 */
 			private function appendRequest()
 			{
 				if ( isset($_SERVER['SCRIPT_FILENAME']) ) {
 					$script = $_SERVER['SCRIPT_FILENAME'];
 				}
 				else {
 					$script = $_SERVER['DOCUMENT_ROOT'] . $_SERVER['PHP_SELF'];
 				}
 
 				$this->appendHTML('ScriptName: <b>' . $this->getFileLink($script, 1, basename($script)) . '</b> (<b>' . dirname($script) . '</b>)');
 				if ( $this->_isAjax ) {
 					$this->appendHTML('RequestURI: ' . $_SERVER['REQUEST_URI'] . ' (QS Length:' . strlen($_SERVER['QUERY_STRING']) . ')');
 				}
 
 				$tools_html = '	<table style="width: ' . $this->getWindowWidth() . 'px;">
 									<tr>
 										<td>' . $this->_getDomViewerHTML() . '</td>
 										<td>' . $this->_getToolsHTML() . '</td>
 									</tr>
 								</table>';
 				$this->appendHTML($tools_html);
 
 				ob_start();
 				?>
 				<table border="0" cellspacing="0" cellpadding="0" class="dbg_flat_table" style="width: <?php echo $this->getWindowWidth(); ?>px;">
 					<thead style="font-weight: bold;">
 						<td width="20">Src</td><td>Name</td><td>Value</td>
 					</thead>
 				<?php
 					$super_globals = Array ('GE' => $_GET, 'PO' => $_POST, 'CO' => $_COOKIE);
 
 					foreach ($super_globals as $prefix => $data) {
 						foreach ($data as $key => $value) {
 							if ( !is_array($value) && trim($value) == '' ) {
 								$value = '<b class="debug_error">no value</b>';
 							}
 							else {
 								$value = htmlspecialchars($this->print_r($value, true), ENT_QUOTES, 'UTF-8');
 							}
 
 							echo '<tr><td>' . $prefix . '</td><td>' . $key . '</td><td>' . $value . '</td></tr>';
 						}
 					}
 				?>
 				</table>
 				<?php
 				$this->appendHTML(ob_get_contents());
 				ob_end_clean();
 			}
 
 			/**
 			 * Appends php session content to debugger output
 			 *
 			 * @return void
 			 * @access private
 			 */
 			private function appendSession()
 			{
 				if ( isset($_SESSION) && $_SESSION ) {
 					$this->appendHTML('PHP Session: [<b>' . ini_get('session.name') . '</b>]');
 					$this->dumpVars($_SESSION);
 					$this->moveToBegin(2);
 				}
 			}
 
 			/**
 			 * Starts profiling of a given $key
 			 *
 			 * @param string $key
 			 * @param string $description
 			 * @param int $timeStamp
 			 * @return void
 			 * @access public
 			 */
 			public function profileStart($key, $description = null, $timeStamp = null)
 			{
 				if ( !isset($timeStamp) ) {
 					$timeStamp = microtime(true);
 				}
 				$this->ProfilerData[$key] = Array ('begins' => $timeStamp, 'ends' => 5000, 'debuggerRowID' => count($this->Data));
 				if ( isset($description) ) {
 					$this->ProfilerData[$key]['description'] = $description;
 				}
 
 				if ( substr($key, 0, 4) == 'sql_' ) {
 					// append place from what was called
 					$trace_results = debug_backtrace();
 					$trace_count = count($trace_results);
 					$i = 0;
 					while ( $i < $trace_count ) {
 						if ( !isset($trace_results[$i]['file']) ) {
 							$i++;
 							continue;
 						}
 
 						$trace_file = basename($trace_results[$i]['file']);
 						if ( $trace_file != 'db_connection.php' && $trace_file != 'db_load_balancer.php' && $trace_file != 'adodb.inc.php' ) {
 							break;
 						}
 						$i++;
 					}
 
 					$this->ProfilerData[$key]['file'] = $trace_results[$i]['file'];
 					$this->ProfilerData[$key]['line'] = $trace_results[$i]['line'];
 
 					if ( isset($trace_results[$i + 1]['object']) && isset($trace_results[$i + 1]['object']->Prefix) ) {
 						$object =& $trace_results[$i + 1]['object'];
 						/* @var $object kBase */
 
 						$prefix_special = rtrim($object->Prefix . '.' . $object->Special, '.');
 						$this->ProfilerData[$key]['prefix_special'] = $prefix_special;
 					}
 
 					unset($trace_results);
 				}
 
 				$this->Data[] = Array ('profile_key' => $key, 'debug_type' => 'profiler');
 			}
 
 			/**
 			 * Ends profiling for a given $key
 			 *
 			 * @param string $key
 			 * @param string $description
 			 * @param int $timeStamp
 			 * @return void
 			 * @access public
 			 */
 			public function profileFinish($key, $description = null, $timeStamp = null)
 			{
 				if ( !isset($timeStamp) ) {
 					$timeStamp = microtime(true);
 				}
 				$this->ProfilerData[$key]['ends'] = $timeStamp;
 
 				if ( isset($description) ) {
 					$this->ProfilerData[$key]['description'] = $description;
 				}
 
 				if ( substr($key, 0, 4) == 'sql_' ) {
 					$func_arguments = func_get_args();
 					$rows_affected = $func_arguments[3];
 
 					$additional = Array ();
 
 					if ( $rows_affected > 0 ) {
 						$additional[] = Array ('name' => 'Affected Rows', 'value' => $rows_affected);
 
 						if ( isset($func_arguments[4]) ) {
 							if ( strlen($func_arguments[4]) > 200 ) {
 								$func_arguments[4] = substr($func_arguments[4], 0, 50) . ' ...';
 							}
 
 							$additional[] = Array ('name' => 'Result', 'value' => $func_arguments[4]);
 						}
 					}
 
 					$additional[] = Array ('name' => 'Query Number', 'value' => $func_arguments[5]);
 
 					if ( $func_arguments[6] ) {
 						$this->profilerAddTotal('cachable_queries', $key);
 						$this->ProfilerData[$key]['subtitle'] = 'cachable';
 					}
 
 					if ( (string)$func_arguments[7] !== '' ) {
 						$additional[] = Array ('name' => 'Server #', 'value' => $func_arguments[7]);
 					}
 
 					if ( array_key_exists('prefix_special', $this->ProfilerData[$key]) ) {
 						$additional[] = Array ('name' => 'PrefixSpecial', 'value' => $this->ProfilerData[$key]['prefix_special']);
 					}
 
 					$this->ProfilerData[$key]['additional'] =& $additional;
 				}
 			}
 
 			/**
 			 * Collects total execution time from profiler record
 			 *
 			 * @param string $total_key
 			 * @param string $key
 			 * @param int $value
 			 * @return void
 			 * @access public
 			 */
 			public function profilerAddTotal($total_key, $key = null, $value = null)
 			{
 				if ( !isset($this->ProfilerTotals[$total_key]) ) {
 					$this->ProfilerTotals[$total_key] = 0;
 					$this->ProfilerTotalCount[$total_key] = 0;
 				}
 
 				if ( !isset($value) ) {
 					$value = $this->ProfilerData[$key]['ends'] - $this->ProfilerData[$key]['begins'];
 				}
 
 				if ( isset($key) ) {
 					$this->ProfilerData[$key]['totalsKey'] = $total_key;
 					$this->ProfilerData[$key]['totalsBefore'] = $this->ProfilerTotals[$total_key];
 				}
 
 				$this->ProfilerTotals[$total_key] += $value;
 				$this->ProfilerTotalCount[$total_key]++;
 			}
 
 			/**
 			 * Traces relative code execution speed between this method calls
 			 *
 			 * @param string $message
 			 * @return void
 			 * @access public
 			 */
 			public function appendTimestamp($message)
 			{
 				global $start;
 
 				$time = microtime(true);
 				$from_last = $time - $this->LastMoment;
 				$from_start = $time - $start;
 				$this->appendHTML(sprintf("<strong>%s</strong> %.5f from last %.5f from start", $message, $from_last, $from_start));
 				$this->LastMoment = $time;
 			}
 
 			/**
 			 * Returns unique ID for each method call
 			 *
 			 * @return int
 			 * @access public
 			 */
 			public 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 = preg_replace('/^0/', '', $id_part_1);
 					$id_part_1 = $digit_one . $id_part_1;
 				}
 
 				return $id_part_1 . $id_part_2 . $id_part_3;
 			}
 
 			/**
 			 * Returns error name based on it's code
 			 *
 			 * @param int $error_code
 			 * @return string
 			 * @access private
 			 */
 			private function getErrorNameByCode($error_code)
 			{
 				$error_map = Array (
 					'Fatal Error' 	=>	Array (E_RECOVERABLE_ERROR, E_USER_ERROR, E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE),
 					'Warning'		=>	Array (E_WARNING, E_USER_WARNING, E_CORE_WARNING, E_COMPILE_WARNING),
 					'Notice'		=>	Array (E_NOTICE, E_USER_NOTICE, E_STRICT),
 				);
 
 				if ( defined('E_DEPRECATED') ) {
 					// since PHP 5.3
 					$error_map['Notice'][] = E_DEPRECATED;
 					$error_map['Notice'][] = E_USER_DEPRECATED;
 				}
 
 				foreach ($error_map as $error_name => $error_codes) {
 					if ( in_array($error_code, $error_codes) ) {
 						return $error_name;
 					}
 				}
 
 				return '';
 			}
 
 			/**
 			 * Returns profile total key (check against missing key too)
 			 *
 			 * @param string $key
 			 * @return int
 			 * @access private
 			 */
 			private function getProfilerTotal($key)
 			{
 				if ( isset($this->ProfilerTotalCount[$key]) ) {
 					return (int)$this->ProfilerTotalCount[$key];
 				}
 
 				return 0;
 			}
 
 			/**
 			 * Counts how much calls were made to a place, where this method is called (basic version of profiler)
 			 *
 			 * @param string $title
 			 * @param int $level
 			 * @return void
 			 * @access public
 			 */
 			public function ProfilePoint($title, $level = 1)
 			{
 				$trace_results = debug_backtrace();
 				$level = min($level, count($trace_results) - 1);
 
 				do {
 					$point = $trace_results[$level];
 					$location = $point['file'] . ':' . $point['line'];
 					$level++;
 					$has_more = isset($trace_results[$level]);
 				} while ( $has_more && $point['function'] == $trace_results[$level]['function'] );
 
 				if ( !isset($this->ProfilePoints[$title]) ) {
 					$this->ProfilePoints[$title] = Array ();
 				}
 
 				if ( !isset($this->ProfilePoints[$title][$location]) ) {
 					$this->ProfilePoints[$title][$location] = 0;
 				}
 
 				$this->ProfilePoints[$title][$location]++;
 			}
 
 			/**
 			 * Generates report
 			 *
 			 * @param bool $returnResult
 			 * @param bool $clean_output_buffer
 			 *
 			 * @return string
 			 * @access public
 			 */
 			public function printReport($returnResult = false, $clean_output_buffer = true)
 			{
 				if ( $this->reportDone ) {
 					// don't print same report twice (in case if shutdown function used + compression + fatal error)
 					return '';
 				}
 
 				$last_error = error_get_last();
 
 				if ( !is_null($last_error) && !$this->_lastErrorProcessed ) {
 					$this->_lastErrorProcessed = true;
 					$this->saveError($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']);
 				}
 
 				$this->profileFinish('script_runtime');
 				$this->breakOutofBuffering(!$returnResult);
 
 				$debugger_start = memory_get_usage();
 
 				if ( defined('SPACER_URL') ) {
 					$this->dummyImage = SPACER_URL;
 				}
 
 				$this->InitReport(); // set parameters required by AJAX
 
 				// defined here, because user can define this constant while script is running, not event before debugger is started
 				DebuggerUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 0);
 				DebuggerUtil::safeDefine('DBG_TOOLBAR_BUTTONS', 1);
 
 				$this->appendSession(); // show php session if any
 
 				// ensure, that 1st line of debug output always is this one:
-				$top_line = '<table cellspacing="0" cellpadding="0" style="width: ' . $this->getWindowWidth() . 'px; margin: 0px;"><tr><td align="left" width="50%">[<a href="javascript:window.location.reload();">Reload Frame</a>] [<a href="javascript:$Debugger.Toggle(27);">Hide Debugger</a>] [<a href="javascript:$Debugger.Clear();">Clear Debugger</a>]</td><td align="right" width="50%">[Current Time: <b>' . date('H:i:s') . '</b>] [File Size: <b>#DBG_FILESIZE#</b>]</td></tr></table>';
+				$top_line = '<table cellspacing="0" cellpadding="0" style="width: ' . $this->getWindowWidth() . 'px; margin: 0px;"><tr><td align="left" width="50%">[<a href="javascript:window.location.reload();">Reload Frame</a>] [<a href="javascript:$Debugger.Toggle(27);">Hide Debugger</a>] [<a href="javascript:$Debugger.Clear();">Clear Debugger</a>]</td><td align="right" width="50%">[Current Time: <b>' . date('H:i:s') . '</b>] [File Size: <b>#DBG_FILESIZE#</b>]</td></tr><tr><td align="left" colspan="2" style="padding-top: 5px;">' . $this->getFilterDropdown() . '</td></tr></table>';
 
 				$this->appendHTML($top_line);
 				$this->moveToBegin(1);
 
 				if ( count($this->ProfilePoints) > 0 ) {
 					foreach ($this->ProfilePoints as $point => $locations) {
 						arsort($this->ProfilePoints[$point]);
 					}
 
 					$this->appendHTML($this->highlightString($this->print_r($this->ProfilePoints, true)));
 				}
 
 				if ( DebuggerUtil::constOn('DBG_SQL_PROFILE') && isset($this->ProfilerTotals['sql']) ) {
 					// sql query profiling was enabled -> show totals
 					if ( array_key_exists('cachable_queries', $this->ProfilerTotalCount) ) {
 						$append = ' <strong>Cachable queries</strong>: ' . $this->ProfilerTotalCount['cachable_queries'];
 					}
 					else {
 						$append = '';
 					}
 
 					$this->appendHTML('<b>SQL Total time:</b> ' . $this->ProfilerTotals['sql'] . ' <b>Number of queries</b>: ' . $this->ProfilerTotalCount['sql'] . $append);
 				}
 
 				if ( DebuggerUtil::constOn('DBG_PROFILE_INCLUDES') && isset($this->ProfilerTotals['includes']) ) {
 					// included file profiling was enabled -> show totals
 					$this->appendHTML('<b>Included Files Total time:</b> ' . $this->ProfilerTotals['includes'] . ' Number of includes: ' . $this->ProfilerTotalCount['includes']);
 				}
 
 				if ( DebuggerUtil::constOn('DBG_PROFILE_MEMORY') ) {
 					// detailed memory usage reporting by objects was enabled -> show totals
 					$this->appendHTML('<b>Memory used by Objects:</b> ' . round($this->ProfilerTotals['objects'] / 1024, 2) . 'Kb');
 				}
 
 				if ( DebuggerUtil::constOn('DBG_INCLUDED_FILES') ) {
 					$files = get_included_files();
 					$this->appendHTML('<strong>Included files:</strong>');
 					foreach ($files as $file) {
 						$this->appendHTML($this->getFileLink($this->getLocalFile($file)) . ' (' . round(filesize($file) / 1024, 2) . 'Kb)');
 					}
 				}
 
 				if ( DebuggerUtil::constOn('DBG_PROFILE_INCLUDES') ) {
 					$totals = $totals_configs = Array ('mem' => 0, 'time' => 0);
 					$this->appendHTML('<b>Included files statistics:</b>' . (DebuggerUtil::constOn('DBG_SORT_INCLUDES_MEM') ? ' (sorted by memory usage)' : ''));
 
 					if ( is_array($this->IncludesData['mem']) ) {
 						if ( DebuggerUtil::constOn('DBG_SORT_INCLUDES_MEM') ) {
 							array_multisort($this->IncludesData['mem'], SORT_DESC, $this->IncludesData['file'], $this->IncludesData['time'], $this->IncludesData['level']);
 						}
 
 						foreach ($this->IncludesData['file'] as $key => $file_name) {
 							$this->appendHTML(str_repeat('&nbsp;->&nbsp;', ($this->IncludesData['level'][$key] >= 0 ? $this->IncludesData['level'][$key] : 0)) . $file_name . ' Mem: ' . sprintf("%.4f Kb", $this->IncludesData['mem'][$key] / 1024) . ' Time: ' . sprintf("%.4f", $this->IncludesData['time'][$key]));
 
 							if ( $this->IncludesData['level'][$key] == 0 ) {
 								$totals['mem'] += $this->IncludesData['mem'][$key];
 								$totals['time'] += $this->IncludesData['time'][$key];
 							}
 							elseif ( $this->IncludesData['level'][$key] == -1 ) {
 								$totals_configs['mem'] += $this->IncludesData['mem'][$key];
 								$totals_configs['time'] += $this->IncludesData['time'][$key];
 							}
 						}
 
 						$this->appendHTML('<b>Sub-Total classes:</b> ' . ' Mem: ' . sprintf("%.4f Kb", $totals['mem'] / 1024) . ' Time: ' . sprintf("%.4f", $totals['time']));
 						$this->appendHTML('<b>Sub-Total configs:</b> ' . ' Mem: ' . sprintf("%.4f Kb", $totals_configs['mem'] / 1024) . ' Time: ' . sprintf("%.4f", $totals_configs['time']));
 						$this->appendHTML('<span class="error"><b>Grand Total:</b></span> ' . ' Mem: ' . sprintf("%.4f Kb", ($totals['mem'] + $totals_configs['mem']) / 1024) . ' Time: ' . sprintf("%.4f", $totals['time'] + $totals_configs['time']));
 					}
 				}
 
 				$skip_reporting = DebuggerUtil::constOn('DBG_SKIP_REPORTING') || DebuggerUtil::constOn('DBG_ZEND_PRESENT');
 
 				if ( ($this->_isAjax && !DebuggerUtil::constOn('DBG_SKIP_AJAX')) || !$skip_reporting ) {
 					$debug_file = $this->tempFolder . '/debug_' . $this->rowSeparator . '.txt';
 					if ( file_exists($debug_file) ) {
 						unlink($debug_file);
 					}
 
 					$i = 0;
 					$fp = fopen($debug_file, 'a');
 					$lineCount = count($this->Data);
 
 					while ( $i < $lineCount ) {
-						fwrite($fp, $this->prepareHTML($i) . $this->rowSeparator);
+						$html = $this->prepareHTML($i);
+						$row_type = $this->getRowType($i);
+
+						fwrite($fp, json_encode(Array ('html' => $html, 'row_type' => $row_type)) . $this->rowSeparator);
 						$i++;
 					}
 
 					fclose($fp);
 				}
 
 				if ( $skip_reporting ) {
 					// let debugger write report and then don't output anything
 					$this->reportDone = true;
 					return '';
 				}
 
 				$application =& kApplication::Instance();
 				$dbg_path = str_replace(FULL_PATH, '', $this->tempFolder);
 
 				$debugger_params = Array (
+					'FilterTypes' => $this->_filterTypes,
 					'RowSeparator' => $this->rowSeparator,
 					'ErrorsCount' => (int)$this->getProfilerTotal('error_handling'),
 					'IsFatalError' => $this->IsFatalError,
 					'SQLCount' => (int)$this->getProfilerTotal('sql'),
 					'SQLTime' => isset($this->ProfilerTotals['sql']) ? sprintf('%.5f', $this->ProfilerTotals['sql']) : 0,
 					'ScriptTime' => sprintf('%.5f', $this->ProfilerData['script_runtime']['ends'] - $this->ProfilerData['script_runtime']['begins']),
 					'ScriptMemory' => DebuggerUtil::formatSize($this->getMemoryUsed($debugger_start)),
 					'Shortcut' => DBG_SHORTCUT,
 				);
 
 				ob_start();
 				// the <script .. /script> and hidden div helps browser to break out of script tag or attribute esacped
 				// with " or ' in case fatal error (or user-error) occurs inside it in compiled template,
 				// otherwise it has no effect
 			?>
 					<div style="display: none" x='nothing'><script></script></div><html><body></body></html>
 					<link rel="stylesheet" rev="stylesheet" href="<?php echo $this->baseURL; ?>/debugger.css?v2" type="text/css" media="screen" />
 					<script type="text/javascript" src="<?php echo $this->baseURL; ?>/debugger.js?v4"></script>
 
 					<script type="text/javascript">
 						var $Debugger = new Debugger(<?php echo json_encode($debugger_params); ?>);
 						$Debugger.createEnvironment(<?php echo DBG_WINDOW_WIDTH; ?>, <?php echo $this->getWindowWidth(); ?>);
 
 						$Debugger.DOMViewerURL = '<?php echo constant('DBG_DOMVIEWER'); ?>';
 						$Debugger.DebugURL = '<?php echo $this->baseURL.'/debugger_responce.php?sid='.$this->rowSeparator.'&path='.urlencode($dbg_path); ?>';
 						$Debugger.EventURL = '<?php echo /*is_object($application->Factory) &&*/ $application->InitDone ? $application->HREF('dummy', '', Array ('pass' => 'm', '__NO_REWRITE__' => 1)) : ''; ?>';
 						$Debugger.BasePath = '<?php echo $this->basePath; ?>';
 						<?php
 							$is_install = defined('IS_INSTALL') && IS_INSTALL;
 
 							if ( $this->IsFatalError || (!$is_install && DBG_RAISE_ON_WARNINGS && $this->WarningCount) ) {
 								echo '$Debugger.Toggle();';
 							}
 							if ( DBG_TOOLBAR_BUTTONS ) {
 								echo '$Debugger.AddToolbar("$Debugger");';
 							}
 						?>
 						window.focus();
 					</script>
 				<?php
 					if ( $returnResult ) {
 						$ret = ob_get_contents();
 						if ( $clean_output_buffer ) {
 							ob_end_clean();
 						}
 						$ret .= $this->getShortReport($this->getMemoryUsed($debugger_start));
 
 						$this->reportDone = true;
 						return $ret;
 					}
 					else {
 						if ( !DebuggerUtil::constOn('DBG_HIDE_FULL_REPORT') ) {
 							$this->breakOutofBuffering();
 						}
 						elseif ( $clean_output_buffer ) {
 							ob_clean();
 						}
 						echo $this->getShortReport($this->getMemoryUsed($debugger_start));
 
 						$this->reportDone = true;
 					}
 
 				return '';
 			}
 
+			function getFilterDropdown()
+			{
+				$filter_options = '';
+
+				foreach ( $this->_filterTypes as $filter_type ) {
+					$filter_options .= '<option value="' . $filter_type . '">' . $filter_type . '</option>';
+				}
+
+				return 'Show: <select id="dbg_filter" onchange="$Debugger.Filter()"><option value="">All</option>' . $filter_options .'</select>';
+			}
+
 			function getMemoryUsed($debugger_start)
 			{
 				if ( !isset($this->ProfilerTotals['error_handling']) ) {
 					$memory_used = $debugger_start;
 					$this->ProfilerTotalCount['error_handling'] = 0;
 				}
 				else {
 					$memory_used = $debugger_start - $this->ProfilerTotals['error_handling'];
 				}
 
 				return $memory_used;
 			}
 
 			/**
 			 * Format's memory usage report by debugger
 			 *
 			 * @param int $memory_used
 			 * @return string
 			 * @access private
 			 */
 			private function getShortReport($memory_used)
 			{
 				if ( DebuggerUtil::constOn('DBG_TOOLBAR_BUTTONS') ) {
 					// evenrything is in toolbar - don't duplicate
 					return '';
 				}
 				else {
 					// toolbar not visible, then show sql & error count too
 					$info = Array (
 						'Script Runtime'	=>	'PROFILE:script_runtime',
 						'SQL\'s Runtime'	=>	'PROFILE_T:sql',
 						'-'					=>	'SEP:-',
 						'Notice / Warning'	=>	'PROFILE_TC:error_handling',
 						'SQLs Count'		=>	'PROFILE_TC:sql',
 					);
 				}
 
 				$ret = ''; // '<tr><td>Application:</td><td><b>' . DebuggerUtil::formatSize($memory_used) . '</b> (' . $memory_used . ')</td></tr>';
 
 				foreach ($info as $title => $value_key) {
 					list ($record_type, $record_data) = explode(':', $value_key, 2);
 					switch ( $record_type ) {
 						case 'PROFILE': // profiler totals value
 							$Data =& $this->ProfilerData[$record_data];
 							$profile_time = ($Data['ends'] - $Data['begins']); // in seconds
 							$ret .= '<tr><td>' . $title . ':</td><td><b>' . sprintf('%.5f', $profile_time) . ' s</b></td></tr>';
 							break;
 
 						case 'PROFILE_TC': // profile totals record count
 							$record_cell = '<td>';
 							if ( $record_data == 'error_handling' && $this->ProfilerTotalCount[$record_data] > 0 ) {
 								$record_cell = '<td class="debug_error">';
 							}
 							$ret .= '<tr>' . $record_cell . $title . ':</td>' . $record_cell . '<b>' . $this->ProfilerTotalCount[$record_data] . '</b></td></tr>';
 							break;
 
 						case 'PROFILE_T': // profile total
 							$record_cell = '<td>';
 							$total = array_key_exists($record_data, $this->ProfilerTotals) ? $this->ProfilerTotals[$record_data] : 0;
 							$ret .= '<tr>' . $record_cell . $title . ':</td>' . $record_cell . '<b>' . sprintf('%.5f', $total) . ' s</b></td></tr>';
 							break;
 
 						case 'SEP':
 							$ret .= '<tr><td colspan="2" style="height: 1px; background-color: #000000; padding: 0px;"><img src="' . $this->dummyImage . '" height="1" alt=""/></td></tr>';
 							break;
 					}
 				}
 
 				return '<br /><table class="dbg_stats_table"><tr><td style="border-color: #FFFFFF;"><table class="dbg_stats_table" align="left">' . $ret . '</table></td></tr></table>';
 			}
 
 			/**
 			 * User-defined error handler
 			 *
 			 * @throws Exception
 			 * @param int $errno
 			 * @param string $errstr
 			 * @param string $errfile
 			 * @param int $errline
 			 * @param array $errcontext
 			 * @return bool
 			 * @access public
 			 */
 			public function saveError($errno, $errstr, $errfile = null, $errline = null, $errcontext = Array ())
 			{
 				$this->ProfilerData['error_handling']['begins'] = memory_get_usage();
 
 				$errorType = $this->getErrorNameByCode($errno);
 
 				if (!$errorType) {
 					throw new Exception('Unknown error type [' . $errno . ']');
 				}
 				elseif ( substr($errorType, 0, 5) == 'Fatal' ) {
 					$this->IsFatalError = true;
 					$this->appendTrace(4);
 				}
 
 				$this->expandError($errstr, $errfile, $errline);
 
 				$this->Data[] = Array (
 					'no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline,
 					'context' => $errcontext, 'debug_type' => 'error'
 				);
 
 				$this->ProfilerData['error_handling']['ends'] = memory_get_usage();
 				$this->profilerAddTotal('error_handling', 'error_handling');
 
 				if ($errorType == 'Warning') {
 					$this->WarningCount++;
 				}
 
 				if ( $this->IsFatalError ) {
 					// append debugger report to data in buffer & clean buffer afterwards
 					die( $this->breakOutofBuffering(false) . $this->printReport(true) );
 				}
 
 				return true;
 			}
 
 			/**
 			 * Adds exception details into debugger but don't cause fatal error
 			 *
 			 * @param Exception $exception
 			 * @return void
 			 * @access public
 			 */
 			public function appendException($exception)
 			{
 				$this->ProfilerData['error_handling']['begins'] = memory_get_usage();
 
 				$this->appendExceptionTrace($exception);
 
 				$errno = $exception->getCode();
 				$errstr = $exception->getMessage();
 				$errfile = $exception->getFile();
 				$errline = $exception->getLine();
 
 				$this->expandError($errstr, $errfile, $errline);
 
 				$this->Data[] = Array (
 					'no' => $errno, 'str' => $errstr, 'file' => $errfile, 'line' => $errline,
 					'exception_class' => get_class($exception), 'debug_type' => 'exception'
 				);
 
 				$this->ProfilerData['error_handling']['ends'] = memory_get_usage();
 				$this->profilerAddTotal('error_handling', 'error_handling');
 			}
 
 			/**
 			 * User-defined exception handler
 			 *
 			 * @param Exception $exception
 			 * @return void
 			 * @access public
 			 */
 			public function saveException($exception)
 			{
 				$this->appendException($exception);
 				$this->IsFatalError = true;
 
 				// append debugger report to data in buffer & clean buffer afterwards
 				die( $this->breakOutofBuffering(false) . $this->printReport(true) );
 			}
 
 			/**
 			 * Transforms short error messages into long ones
 			 *
 			 * @param string $errstr
 			 * @param string $errfile
 			 * @param int $errline
 			 * @return void
 			 * @access private
 			 */
 			private function expandError(&$errstr, &$errfile, &$errline)
 			{
 				$errstr = kLogger::expandMessage($errstr);
 				list ($errno, $errstr, $sql) = kLogger::parseDatabaseError($errstr);
 
 				if ( $errno != 0 ) {
 					$errstr = '<span class="debug_error">' . $errstr . ' (' . $errno . ')</span><br/><strong>SQL</strong>: ' . $this->formatSQL($sql);
 				}
 
 				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);
 				}
 			}
 
 			/**
 			 * Break buffering in case if fatal error is happened in the middle
 			 *
 			 * @param bool $flush
 			 * @return string
 			 * @access private
 			 */
 			private function breakOutofBuffering($flush = true)
 			{
 				$buffer_content = Array ();
 				while ( ob_get_level() ) {
 					$buffer_content[] = ob_get_clean();
 				}
 
 				$ret = implode('', array_reverse($buffer_content));
 				if ( $flush ) {
 					echo $ret;
 					flush();
 				}
 
 				return $ret;
 			}
 
 			/**
 			 * Saves given message to "vb_debug.txt" file in DocumentRoot
 			 *
 			 * @param string $msg
 			 * @return void
 			 * @access public
 			 */
 			public function saveToFile($msg)
 			{
 				$fp = fopen($_SERVER['DOCUMENT_ROOT'] . '/vb_debug.txt', 'a');
 				fwrite($fp, $msg . "\n");
 				fclose($fp);
 			}
 
 			/**
 			 * Prints given constant values in a table
 			 *
 			 * @param mixed $constants
 			 * @return void
 			 * @access public
 			 */
 			public function printConstants($constants)
 			{
 				if ( !is_array($constants) ) {
 					$constants = explode(',', $constants);
 				}
 
 				$constant_tpl = '<tr><td>%s</td><td><b>%s</b></td></tr>';
 				$ret = '<table class="dbg_flat_table" style="width: ' . $this->getWindowWidth() . 'px;">';
 
 				foreach ($constants as $constant_name) {
 					$ret .= sprintf($constant_tpl, $constant_name, constant($constant_name));
 				}
 
 				$ret .= '</table>';
 				$this->appendHTML($ret);
 			}
 
 			/**
 			 * Attaches debugger to Application
 			 *
 			 * @return void
 			 * @access public
 			 */
 			public function AttachToApplication()
 			{
 				if ( !DebuggerUtil::constOn('DBG_HANDLE_ERRORS') ) {
 					return;
 				}
 
 				if ( class_exists('kApplication') ) {
 					$this->Application =& kApplication::Instance();
 					$this->Application->Debugger = $this;
 				}
 
 				// kLogger will auto-detect these automatically
 				// error/exception handlers registered before debugger will be removed!
 				set_error_handler( Array ($this, 'saveError') );
 				set_exception_handler( Array ($this, 'saveException') );
 			}
 
 			/**
 			 * Returns HTML for tools section
 			 *
 			 * @return string
 			 * @access private
 			 */
 			private function _getToolsHTML()
 			{
 				$html = '<table>
 							<tr>
 								<td>System Tools:</td>
 								<td>
 									<select id="reset_cache" style="border: 1px solid #000000;">
 										<option value=""></option>
 										<option value="events[adm][OnResetModRwCache]">Reset mod_rewrite Cache</option>
 										<option value="events[adm][OnResetCMSMenuCache]">Reset SMS Menu Cache</option>
 										<option value="events[adm][OnResetSections]">Reset Sections Cache</option>
 										<option value="events[adm][OnResetConfigsCache]">Reset Configs Cache</option>
 										<option value="events[adm][OnRebuildThemes]">Re-build Themes Files</option>
 										<option value="events[lang][OnReflectMultiLingualFields]">Re-build Multilanguage Fields</option>
 										<option value="events[adm][OnDeleteCompiledTemplates]">Delete Compiled Templates</option>
 									</select>
 								</td>
 								<td>
 									<input type="button" class="button" onclick="$Debugger.resetCache(\'reset_cache\');" value="Go"/>
 								</td>
 							</tr>
 						</table>';
 
 				return $html;
 			}
 
 			/**
 			 * Returns HTML for dom viewer section
 			 *
 			 * @return string
 			 * @access private
 			 */
 			private function _getDomViewerHTML()
 			{
 				$html = '<table>
 							<tr>
 								<td>
 									<a href="http://www.brainjar.com/dhtml/domviewer/" target="_blank">DomViewer</a>:
 								</td>
 								<td>
 									 <input id="dbg_domviewer" type="text" value="window" style="border: 1px solid #000000;"/>
 								</td>
 								<td>
 									<button class="button" onclick="return $Debugger.OpenDOMViewer();">Show</button>
 								</td>
 							</tr>
 						</table>';
 
 				return $html;
 			}
 		}
 
 		if ( !function_exists('memory_get_usage') ) {
 			// PHP 4.x and compiled without --enable-memory-limit option
 			function memory_get_usage()
 			{
 				return -1;
 			}
 		}
 
 		if ( !DebuggerUtil::constOn('DBG_ZEND_PRESENT') ) {
 			$debugger = new Debugger();
 		}
 
 		if ( DebuggerUtil::constOn('DBG_USE_SHUTDOWN_FUNC') ) {
 			register_shutdown_function(Array (&$debugger, 'printReport'));
 		}
 	}