<?php
// 	This file is part of htmlMicroscope
//	Written & copyrighted (c) 2010 by Rene AJM Veerman <rene7705@gmail.com>
//	License: LGPL
//	NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
//	Download: http://mediabeez.ws/htmlMicroscope/

//require_once ('lib_duration.php');


// [OPTIONAL], 
//	makes available simplistic pure-html dump functions;
//	(no javascript interactions) 
//
//	htmlDump($var, $title); //outputs directly to page
//	htmlDumpReturn ($var, $title); // returns HTML string that htmlDump() would output to page.
//require_once ('../lah/lib_html.php');
// [/OPTIONAL]

ini_set ('allow_call_time_pass_reference', true);

// ---
//      PUBLIC functions :

function hm (&$var, $title, $options=null) {
  htmlMicroscope_dump ($var, $title, $options);
}

function hmJSON (&$jsonString, $title, $options=null) {
	htmlMicroscope_dumpJSON ($jsonString, $title, $options);
}





// ---
//      PRIVATE functions :

global $hmConfig;
$hmConfig = null;
function htmlMicroscope_config ($overrides=null) {
    global $hmConfig;
    if (!$hmConfig) {
		$hmConfig = htmlMicroscope_config_authorsDefaults();
    }
    if (is_array($overrides)) {
		$hmConfig = negotiateOptions(
		  $hmConfig,
		  $overrides
		);
    }
    if (!array_key_exists('developerVisitors', $hmConfig)) {
		$hmConfig['developerVisitors'] = array (
		// ONLY if your webbrowser IP ($_SERVER['REMOTE_ADDR']) is listed here, 
		// is the browser allowed the use of random-array generator functions (index.php?fresh=true)

		  '192.168.1.33' => array(), // array() === for future extension, overrides of settings per visitor ip.
		  '82.161.37.94' => array()
		);
	}
	if (!array_key_exists('debug', $hmConfig)) {
		$hmConfig['debug'] = true;
	}	
    return $hmConfig;
}

function htmlMicroscope_headIncludes ($hms=null) {
    if (!$hms) $hms=htmlMicroscope_config();
    $bd = $hms['baseDir'];
    $bu = $hms['baseURL'];
    $dbg = $hms['debug'];
/*
<script language='JavaScript1.3' type='text/javascript' src='<?php echo $bu?>jquery-1.3.2<?php echo ($dbg?'.source':'.min')?>.js'></script>
*/
?>
    <script language='JavaScript1.3' type='text/javascript' src='<?php echo $bu?>hm<?php echo ($dbg?'.source':'.min')?>.js'></script>
    <script language='JavaScript1.3' type='text/javascript'>
      hms.options.current.rootURL = '<?php echo $bu?>';
    </script>
<?php
}

function htmlMicroscope_headOptions () {
	$hms = htmlMicroscope_config();
?>
	<script type='text/javascript'><!-- 
		hms.options.current.rootURL = '<?php echo $hms['baseURL']?>'; 
	--></script>
<?php
}

function htmlMicroscope_config_authorsDefaults () {
	$hmConfig = array (
	'debug' => true, //use FALSE to use the minimized version of the script
		'developerVisitors' => array (
		// debug === true for any developer visitors.
		  '192.168.1.33' => array(), // array() === for future extension, overrides of settings per visitor ip.
		  '82.161.37.94' => array()
		)
	);

    $hmConfig['version'] = '1.4.0';
    $hmConfig['releaseDate'] = '2011 july 13, 10:40 CEST';
		//'hm.php'.': '.date('r',filectime (HD_ROOT.'code/libraries_rv/htmlMicroscope-1.3.3/hm.php')).', '.
		//'hm.source.js'.': '.date('r',filectime (HD_ROOT.'code/libraries_rv/htmlMicroscope-1.3.3/hm.source.js'));
    $hmConfig['baseDir'] = HD_ROOT.'code/libraries_rv/htmlMicroscope-1.4.0/';
    $hmConfig['baseURL'] = WWW_ROOT.'code/libraries_rv/htmlMicroscope-1.4.0/';
    
    return $hmConfig;

};

function htmlMicroscope_visitorIsDeveloper() {
  $cfg = htmlMicroscope_config();
  foreach ($cfg['developerVisitors'] as $ip=>$ipsettings) {
    if ($_SERVER['REMOTE_ADDR']==$ip) {
      return true;
    }
  }
  return false;
}

global $hmOutput;
$hmOutput = '';

global $hmTopIdx;
$hmTopIdx = 0;

function htmlMicroscope_output ($str, $direct) {
  if ($direct) {
    echo $str; 
  } else {
    global $hmOutput;
    $hmOutput.=$str;
  }
}

function htmlMicroscope_dump ($var, $title, $options=null, $hmSettings=null, $direct=true) {
  if (!$hmSettings) $hmSettings = htmlMicroscope_config();
  
  global $hmTopIdx;
  $id = $hmTopIdx++;
  $htmlID = 'scope'.$id;
 
  global $jesx_idPrefix;
  
  global $hmOutput;
  $hmOutput = '';

  $options = ($options ? json_encode_safe($options,true) : null);
	$traceData=debug_backtrace();
  $traceData = htmlMicroscope_filterTrace_forPHP($traceData, array(
		'filter' => array(
						'badResult' => 'removeCompletely',
						'nonFatalErrorHandler' => 'removeCompletely',
						'htmlMicroscope_dump' => 'removeCompletely',
						'hm' => 'removeCompletely'
		)
	));
	/*
	echo 't777: <pre>';
	var_dump ($traceData);
	echo '</pre>';
	 */
  $trace = array(
      'hmOverrides' => array (
	'themeName' => '--trace--'
	//'urlEditor' => $hmSettings['urlEditor']
       ),
       'traceData' => $traceData
  );
  //htmlDump ($trace, "td2");
  htmlMicroscope_output ('<div id="'.$htmlID.'" class="htmlMicroscope hm hmPreInit">', $direct);
    htmlMicroscope_output ('<div id="'.$htmlID.'_hmPreInit" class="hmPreInit">', $direct);
      htmlMicroscope_output ('<div id="'.$htmlID.'_titleSpan" class="hmPItitle"><a href="http://mediabeez.ws/htmlMicroscope/">htmlMicroscope</a> '.$title.'</div> ', $direct);
      if (2==1) {
				$b = strlen(serialize($var)); //i suspect serialize to be slow and prone to memory hogging.
				htmlMicroscope_output ('<div id="'.$htmlID.'_dataSize" class="hmPIdataSize">Receiving '.$b.' bytes, '.filesizeHumanReadable($b).' of data.<br/><br/></div>', $direct);
      } else {
				htmlMicroscope_output ('<div id="'.$htmlID.'_dataSize" class="hmPIdataSize">Receiving data.<br/><br/></div>', $direct);
      }
      htmlMicroscope_output ('<div id="'.$htmlID.'_preInitStatus" class="hm hmPreInitStatus" style="display:none">', $direct);
      htmlMicroscope_output ('<span id="'.$htmlID.'_longMsg" class="hmPIlongMsg"> </span><br/>', $direct);
      htmlMicroscope_output ('<span id="'.$htmlID.'_shortMsg" class="hmPIshortMsg"> </span>', $direct);  
    htmlMicroscope_output ('</div>', $direct);
    $jesx_idPrefix = $htmlID.'_tracedata_';
		$traceJSON = json_prepare($trace);
    json_encode_safer_xxl ($traceJSON);

    $jesx_idPrefix = $htmlID.'_data_';
    //htmlMicroscope_output ('<div id="'.$jesx_idPrefix.'" style="display:none">'."\n", $direct);
    $var = json_prepare($var);
    json_encode_safer_xxl ($var);
    htmlMicroscope_output ("\n".'</div>'."\n", $direct);
/*
    htmlMicroscope_output ('<div id="'.$htmlID.'_tracedata" style="display:none"><!-- ', $direct);
      json_encode_safer (json_prepare($traceData), false);
    htmlMicroscope_output (' --></div>'."\n", $direct);
     
    htmlMicroscope_output ('<div id="'.$htmlID.'_data" style="display:none"><!-- ', $direct);
    ($direct ? 
      json_encode_safer (json_prepare($var), false)
    :
      htmlMicroscope_output (json_encode_safe (json_prepare($var), false), $direct)
    );
    htmlMicroscope_output (' --></div>', $direct);    
*/    
  htmlMicroscope_output ('</div>', $direct);
  htmlMicroscope_output ('<script type="text/javascript">', $direct);
  htmlMicroscope_output ('var hmData = {', $direct);
  htmlMicroscope_output (' "title" : "'.$title.'", ', $direct);
  htmlMicroscope_output (' "date" : "'.date('r').'",', $direct);
  htmlMicroscope_output (' "time" : "'.getDuration().'",', $direct);
  htmlMicroscope_output (' "options" : '.($options?'"'.$options.'"':'null').', ', $direct);
  htmlMicroscope_output (' "trace" : null, ', $direct);
/*
  htmlMicroscope_output (' "trace" : "', $direct);
  ( $direct ?
      json_encode_safer (json_prepare($trace), true)
  :
      htmlMicroscope_output (json_encode_safe (json_prepare($trace), true), $direct)
  );
  htmlMicroscope_output ('", ', $direct);
*/  
  htmlMicroscope_output (' "id" : "'.$htmlID.'", ', $direct);
  htmlMicroscope_output (' "dataOrigin" : "php"', $direct);
  htmlMicroscope_output ('};'."\n", $direct);
  htmlMicroscope_output ('rajmv.htmlMicroscope.process (hmData); '."\n", $direct);
  htmlMicroscope_output ('</script>'."\n", $direct);
  if ($direct) return true; else return $hmOutput;
}

function htmlMicroscope_dumpJSON ($jsonString, $title, $options=null, $hmSettings=null, $direct=true) {
  if (!$hmSettings) $hmSettings = htmlMicroscope_config();
  
  global $hmTopIdx;
  $id = $hmTopIdx++;
  $htmlID = 'scope'.$id;
 
  global $jesx_idPrefix;
  
  global $hmOutput;
  $hmOutput = '';

  $options = ($options ? json_encode_safe($options,true) : null);
  $traceData=debug_backtrace();
  $traceData = htmlMicroscope_filterTrace_forPHP($traceData, array(
		'filter' => array(
//						'badResult' => 'removeCompletely',
						//'nonFatalErrorHandler' => 'removeCompletely',
						//'htmlMicroscope_dump' => 'removeCompletely',
						//'hm' => 'removeCompletely'
		)
	));
  $trace = array(
      'hmOverrides' => array (
	'themeName' => '--trace--'
	//'urlEditor' => $hmSettings['urlEditor']
       ),
       'traceData' => $traceData
  );
  //htmlDump ($trace, "td2");
  htmlMicroscope_output ('<div id="'.$htmlID.'" class="htmlMicroscope hm hmPreInit">', $direct);
    htmlMicroscope_output ('<div id="'.$htmlID.'_hmPreInit" class="hmPreInit">', $direct);
      htmlMicroscope_output ('<div id="'.$htmlID.'_titleSpan" class="hmPItitle"><a href="http://mediabeez.ws/htmlMicroscope/">htmlMicroscope</a> '.$title.'</div> ', $direct);
      if (false) {
				$b = strlen(serialize($var)); //i suspect serialize to be slow and prone to memory hogging.
				htmlMicroscope_output ('<div id="'.$htmlID.'_dataSize" class="hmPIdataSize">Receiving '.$b.' bytes, '.filesizeHumanReadable($b).' of data.<br/><br/></div>', $direct);
      } else {
				htmlMicroscope_output ('<div id="'.$htmlID.'_dataSize" class="hmPIdataSize">Receiving data.<br/><br/></div>', $direct);
      }
      htmlMicroscope_output ('<div id="'.$htmlID.'_preInitStatus" class="hm hmPreInitStatus" style="display:none">', $direct);
      htmlMicroscope_output ('<span id="'.$htmlID.'_longMsg" class="hmPIlongMsg"> </span><br/>', $direct);
      htmlMicroscope_output ('<span id="'.$htmlID.'_shortMsg" class="hmPIshortMsg"> </span>', $direct);  
    htmlMicroscope_output ('</div>', $direct);
    $jesx_idPrefix = $htmlID.'_tracedata_';
		$traceJSON = json_prepare($trace);
    json_encode_safer_xxl ($traceJSON);

    $jesx_idPrefix = $htmlID.'_data_';
    htmlMicroscope_output ('<div id="'.$jesx_idPrefix.'0" style="display:none">'."\n", $direct);
    htmlMicroscope_output ('<!-- '.$jsonString.' -->', $direct);
    htmlMicroscope_output ("\n".'</div>'."\n", $direct);
/*
    htmlMicroscope_output ('<div id="'.$htmlID.'_tracedata" style="display:none"><!-- ', $direct);
      json_encode_safer (json_prepare($traceData), false);
    htmlMicroscope_output (' --></div>'."\n", $direct);
     
    htmlMicroscope_output ('<div id="'.$htmlID.'_data" style="display:none"><!-- ', $direct);
    ($direct ? 
      json_encode_safer (json_prepare($var), false)
    :
      htmlMicroscope_output (json_encode_safe (json_prepare($var), false), $direct)
    );
    htmlMicroscope_output (' --></div>', $direct);    
*/    
  htmlMicroscope_output ('</div>', $direct);
  htmlMicroscope_output ('</div>', $direct);
  htmlMicroscope_output ('<script type="text/javascript">', $direct);
  htmlMicroscope_output ('var hmData = {', $direct);
  htmlMicroscope_output (' "title" : "'.$title.'", ', $direct);
  htmlMicroscope_output (' "date" : "'.date('r').'",', $direct);
  htmlMicroscope_output (' "time" : "'.getDuration().'",', $direct);
  htmlMicroscope_output (' "options" : '.($options?'"'.$options.'"':'null').', ', $direct);
  htmlMicroscope_output (' "trace" : null, ', $direct);
/*
  htmlMicroscope_output (' "trace" : "', $direct);
  ( $direct ?
      json_encode_safer (json_prepare($trace), true)
  :
      htmlMicroscope_output (json_encode_safe (json_prepare($trace), true), $direct)
  );
  htmlMicroscope_output ('", ', $direct);
*/  
  htmlMicroscope_output (' "id" : "'.$htmlID.'", ', $direct);
  htmlMicroscope_output (' "dataOrigin" : "php"', $direct);
  htmlMicroscope_output ('};'."\n", $direct);
  htmlMicroscope_output ('rajmv.htmlMicroscope.process (hmData); '."\n", $direct);
  htmlMicroscope_output ('</script>'."\n", $direct);
  if ($direct) return true; else return $hmOutput;
}



function htmlMicroscope_filterTrace_forPHP (&$t,$s=null) {
// $t = trace data from debug_backtrace()
// $s = settings
		$r = array();
		$t = array_reverse ($t);
		foreach ($t as $k => &$l) {

			$skip = false;
			if (array_key_exists('filter', $s)) {
				foreach ($s['filter'] as $k=>$v) {
					if ($l['function']==$k) {
						if ($v=='removeCompletely') { $skip = true; break; };
						if ($v=='removeArg0') { $l['args'][0] = 'htmlMicroscope: removed to eliminate redundancy.'; };
					}
				}
			}

			if (!$skip) {
				if (array_key_exists('removeFromFilePath', $s) && array_key_exists('file', $l)) {
					$l['file'] = str_replace($s['removeFromFilePath'], '', $l['file']);
				} 
				
				
				$context = array();
				$context['function'] = $l['function'];
				if (array_key_exists('file',$l)) $context['file'] = $l['file'];
				if (array_key_exists('line',$l)) $context['line'] = $l['line'];
				$id = json_encode($context);
				
				if (array_key_exists('args',$l)) $r[$id] = $l['args'];
			}
		}

return $r;
		
    return array_merge(array(
			'hmOverrides'=>array(
				'themeName'=>'--trace--'
			)),$r
		);
}

function json_prepare (&$v) {
  $r = json_prepare_forPHP ($v);
  return $r;
}

function json_prepare_forPHP (&$v) {
  if (is_array($v)) {
    foreach ($v as $k=>&$w) {
		if ($k!==0 && ($k=='' || is_null($k))) {
			unset ($v[$k]);
			$k='__nullKey__';
		};
		$v[$k] = json_prepare_forPHP ($w);
    }
  } elseif (is_object($v)) {
		$v = '[php object]';
  } elseif (is_resource($v)) {
    $v = '[php resource '.get_resource_type($v).' '.$v.']';
  }
  return $v;
}

// constants
global $jesx_idPrefix;
global $jesx_chunkSize;
$jesx_chunkSize = 1 * 1024 * 1024;

// variables
global $jesx_cntChunkBytesDone;
$jesx_cntChunkBytesDone = 0;

global $jesx_cntChunks;
$jesx_cntChunks = 0;

global $jecstf_idPrefix;
$jecstf_idPrefix = 'jsonEncodeChunkedSafe__';

global $jecstf_cntChunkBytesDone;
$jecstf_cntChunkBytesDone = 0;

global $jecstf_cntChunks;
$jecstf_cntChunks = 0;

function json_encode_chunked_safe_toFile ($f, &$a, $baseID='jsonEncodeChunkedSafe__', $extraEscaping=false, $isKey=false) {
	global $jecstf_cntChunkBytesDone;
	$jecstf_cntChunkBytesDone = 0;
	global $jecstf_cntChunks;
	$jecstf_cntChunks = 0;
	global $jecstf_idPrefix;
	$jecstf_idPrefix = $baseID;
	json_encode_chunked_safe_toFile_do ($f, $a, $extraEscaping, $isKey);
	json_encode_chunked_safe_toFile_seperatorEnd ($f);
}

function json_encode_chunked_safe_toFile_seperatorStart ($f) {
  global $jecstf_cntChunks;
  global $jecstf_idPrefix;
  fwrite ($f, '<div id="'.$jecstf_idPrefix.$jecstf_cntChunks.'" style="display:none"><!-- ');
}

function json_encode_chunked_safe_toFile_seperatorEnd ($f) {
  fwrite ($f, ' --></div>'."\n");
}

function json_encode_chunked_safe_toFile_do ($f, &$a, $extraEscaping=false, $isKey=false) {
global $jecstf_cntChunkBytesDone;
global $jesx_chunkSize;
global $jecstf_cntChunks;


    if ($jecstf_cntChunkBytesDone > $jesx_chunkSize) {
      json_encode_chunked_safe_toFile_seperatorEnd($f);
      $jecstf_cntChunkBytesDone = 0;
      $jecstf_cntChunks++;
    }
    if ($jecstf_cntChunkBytesDone==0) {
      json_encode_chunked_safe_toFile_seperatorStart($f);
    }

	if (is_null($a) || is_bool($a)) {
	  if (is_null($a)) $r = 'null';
	  if ($a===false) $r = 'false';
	  if ($a===true) $r = 'true';
	  if ($isKey) {
	    if ($extraEscaping) {
	      $r = '\"'.$r.'\"';
	    } else {
	      $r = '"'.$r.'"';
	    }
	  } 
	  fwrite ($f, $r);
	  $jecstf_cntChunkBytesDone+= strlen($r);
	} else if (is_int($a) || is_float($a)) {
	  if ($isKey) {
	    if ($extraEscaping) {
				fwrite ($f, '\"'.$a.'\"');
	    } else {
	      fwrite ($f, '"'.$a.'"');
	    }
	  } else {
	    fwrite ($f, ''.$a);
	  }
	  $jecstf_cntChunkBytesDone += strlen($a);
	} else if (is_string($a)) {
	    $b = '';
	    if ($a=='') {
	      //if ($extraEscaping) echo '\"\"'; else echo '""';
	    } else {
	      $esc = '\\';
	      $skip = 0;
	      for ($i=0; $i<strlen($a); $i++) {
		if ($skip>0) {
		  $i += $skip;
		  if ($i>=strlen($a)) break;
		  $skip = 0;
		}
		$c = substr($a,$i,3);
		if (
		  $c=='\\u' ||
		  $c=='\\\\'
		) {
		  //skip!
		} elseif ($c=='-->') {
		  $c = '--|>'; //break HTML comment endings, coz it'll break the js decoding
		  $b.= $c;
		  $skip = 2;
		} else {
		  $c = substr($c, 0, 1);
		  if (
		    $c == ' ' || 
		    $c == '"' ||
		    $c == "'" ||
		    $c == "\t" ||
		    $c == "\n" || //TODO try
		    $c == "\r" ||
		    $c == ')' || 
		    $c == '(' || 
		    ( $c>='a' && $c<='z') ||
		    ( $c>='A' && $c<='Z') ||
		    ( $c>='0' && $c<='9') ||
		    $c == '.' || 
		    $c == '-' || 
		    $c == '_' || 
		    $c == '%' || 
		    $c == '!' || 
		    $c == '#' || 
		    $c == '$' || 
		    $c == '%' || 
		    $c == '&' || 
		    $c == '^' || 
		    $c == ',' || 
		    $c == ':' || 
		    $c == ';' || 
		    $c == '=' || 
		    $c == '?' || 
		    $c == '@' || 
		    $c == '`' || 
		    $c == '~' || 
		    $c == '|' || 
		    $c == '>' ||
		    $c == '<' ||
		    $c == '}' ||
		    $c == '{' ||
		    $c == ']' ||
		    $c == '[' ||
		    $c == '/' ||
		    $c == '+' ||
		    $c == '\\' 
		  ) {
		    //if ($c=="'") $c = '\\\'';
		    if ($c=='/') $c = '\\/';
		    elseif ($c=='\\') $c = '\\\\';
		    elseif ($c=='"') $c = '\\"';//$c= '~`';
		    elseif ($c=="\n") $c = '\\n';
		    elseif ($c=="\r") $c = '\\r';
		    elseif ($c=="\t") $c = '\\t';
		  } else {
		    $c = dechex(ord($c));
		    if (strlen($c)==1) $c= '000'.$c;
		    elseif (strlen($c)==2) $c= '00'.$c;
		    elseif (strlen($c)==3) $c= '0'.$c;
		    $c = $esc.'u'.$c;
		  }
		  $b.=$c;
		}
	      }
	    }	
	    if ($extraEscaping) {
	      //echo '\u0022';
	      fwrite ($f, '\"');
	      fwrite ($f, $b);
	      //echo '\u0022';
	      fwrite ($f, '\"');
	      $jecstf_cntChunkBytesDone += 4 + strlen($b);
	    } else {
	      fwrite ($f, '"');
	      fwrite ($f, $b);
	      fwrite ($f, '"');
	      $jecstf_cntChunkBytesDone += 2 + strlen($b);
	    }
	    return true;
        } elseif (is_array($a)) {
	  $isList = true;
	  $isListStartingAt1 = false;
	  for ($i=0, reset($a); $i<count($a); $i++, next($a)) {
	      if (key($a) !== $i) { $isList = false; break; }
	  }
	  if (!$isList) {
	    //allow for numeric arrays starting at 1
	    $isList = true;
	    $isListStartingAt1 = true;
	    for ($i=1, reset($a); $i<=count($a); $i++, next($a))
		if (key($a) !== $i) { $isList = false; break; }
	  }
	  if ($isList) {
	      fwrite ($f, '[');
	      $jecstf_cntChunkBytesDone += 1;
	      if ($isListStartingAt1) {
				if ($extraEscaping) {
				  fwrite ($f, '\"hmDeleteMe\",'); //so the receiving end starts at 1 too
				  $jecstf_cntChunkBytesDone += 15;
				} else {
				  fwrite ($f, '"hmDeleteMe",'); //so the receiving end starts at 1 too
				  $jecstf_cntChunkBytesDone += 13;
				}
	      }
	      $first = true;
	      foreach ($a as $v) {
				if ($first) { $first = false; } else { fwrite ($f, ',');  $jecstf_cntChunkBytesDone += 1; }
				json_encode_chunked_safe_toFile_do ($f, $v,$extraEscaping);
	      }
	      fwrite ($f, ']');
	      $jecstf_cntChunkBytesDone += 1;
	  } else {
	      fwrite ($f, '{');
	      $jecstf_cntChunkBytesDone += 1;
	      $first = true;
	      foreach ($a as $k=>$v) {
			  if ($k=='hmOverrides') {
			    if (is_array($v) && array_key_exists('jsonMe', $v)) {
			      if ($v['jsonMe'] == true) $extraEscaping = true;
			    }
			  }
			  if ($first) { $first = false; } else { fwrite ($f,','); }
			  json_encode_chunked_safe_toFile_do ($f, $k,$extraEscaping, true);
			  fwrite ($f, ':');
			  $jecstf_cntChunkBytesDone += 1;
			  json_encode_chunked_safe_toFile_do ($f, $v,$extraEscaping);
	      }
	      fwrite ($f, '}');
	      $jecstf_cntChunkBytesDone += 1;
	  }
	}
//  ob_flush(); //flush the output buffer
  return true;
}



function json_encode_safer_xxl (&$a, $extraEscaping=false, $isKey=false) {
  global $jesx_cntChunkBytesDone;
  $jesx_cntChunkBytesDone = 0;
  json_encode_safer_xxl_do ($a, $extraEscaping, $isKey);
  json_encode_safer_xxl_seperatorEnd();
}

function json_encode_safer_xxl_seperatorStart () {
  global $jesx_cntChunks;
  global $jesx_idPrefix;
  echo '<div id="'.$jesx_idPrefix.$jesx_cntChunks.'" style="display:none"><!-- ';
}

function json_encode_safer_xxl_seperatorEnd () {
  echo ' --></div>'."\n";
}

function json_encode_safer_xxl_do (&$a, $extraEscaping=false, $isKey=false) {
//was formerly php_js() by php at koterov dot ru, 
// somewhat modified by rene7705@gmail.com
// this version outputs in chunks to different DIVs.
// browsers dont like strings (even comment strings) > 60 Mb or so (2010/01)
global $jesx_cntChunkBytesDone;
global $jesx_chunkSize;
global $jesx_cntChunks;


    if ($jesx_cntChunkBytesDone > $jesx_chunkSize) {
      json_encode_safer_xxl_seperatorEnd();
      $jesx_cntChunkBytesDone = 0;
      $jesx_cntChunks++;
    }
    if ($jesx_cntChunkBytesDone==0) {
      json_encode_safer_xxl_seperatorStart();
    }

	if (is_null($a) || is_bool($a)) {
	  if (is_null($a)) $r = 'null';
	  if ($a===false) $r = 'false';
	  if ($a===true) $r = 'true';
	  if ($isKey) {
	    if ($extraEscaping) {
	      $r = '\"'.$r.'\"';
	    } else {
	      $r = '"'.$r.'"';
	    }
	  } 
	  echo $r;
	  $jesx_cntChunkBytesDone+= strlen($r);
	} else if (is_int($a) || is_float($a)) {
	  if ($isKey) {
	    if ($extraEscaping) {
				echo '\"'.$a.'\"';
	    } else {
	      echo '"'.$a.'"';
	    }
	  } else {
	    echo ''.$a;
	  }
	  $jesx_cntChunkBytesDone += strlen($a);
	} else if (is_string($a)) {
	    $b = '';
	    if ($a=='') {
	      //if ($extraEscaping) echo '\"\"'; else echo '""';
	    } else {
	      $esc = '\\';
	      $skip = 0;
	      for ($i=0; $i<strlen($a); $i++) {
		if ($skip>0) {
		  $i += $skip;
		  if ($i>=strlen($a)) break;
		  $skip = 0;
		}
		$c = substr($a,$i,3);
		if (
		  $c=='\\u' ||
		  $c=='\\\\'
		) {
		  //skip!
		} elseif ($c=='-->') {
		  $c = '--|>'; //break HTML comment endings, coz it'll break the js decoding
		  $b.= $c;
		  $skip = 2;
		} else {
		  $c = substr($c, 0, 1);
		  if (
		    $c == ' ' || 
		    $c == '"' ||
		    $c == "'" ||
		    $c == "\t" ||
		    $c == "\n" || //TODO try
		    $c == "\r" ||
		    $c == ')' || 
		    $c == '(' || 
		    ( $c>='a' && $c<='z') ||
		    ( $c>='A' && $c<='Z') ||
		    ( $c>='0' && $c<='9') ||
		    $c == '.' || 
		    $c == '-' || 
		    $c == '_' || 
		    $c == '%' || 
		    $c == '!' || 
		    $c == '#' || 
		    $c == '$' || 
		    $c == '%' || 
		    $c == '&' || 
		    $c == '^' || 
		    $c == ',' || 
		    $c == ':' || 
		    $c == ';' || 
		    $c == '=' || 
		    $c == '?' || 
		    $c == '@' || 
		    $c == '`' || 
		    $c == '~' || 
		    $c == '|' || 
		    $c == '>' ||
		    $c == '<' ||
		    $c == '}' ||
		    $c == '{' ||
		    $c == ']' ||
		    $c == '[' ||
		    $c == '/' ||
		    $c == '+' ||
		    $c == '\\' 
		  ) {
		    //if ($c=="'") $c = '\\\'';
		    if ($c=='/') $c = '\\/';
		    elseif ($c=='\\') $c = '\\\\';
		    elseif ($c=='"') $c = '\\"';//$c= '~`';
		    elseif ($c=="\n") $c = '\\n';
		    elseif ($c=="\r") $c = '\\r';
		    elseif ($c=="\t") $c = '\\t';
		  } else {
		    $c = dechex(ord($c));
		    if (strlen($c)==1) $c= '000'.$c;
		    elseif (strlen($c)==2) $c= '00'.$c;
		    elseif (strlen($c)==3) $c= '0'.$c;
		    $c = $esc.'u'.$c;
		  }
		  $b.=$c;
		}
	      }
	    }	
	    if ($extraEscaping) {
	      //echo '\u0022';
	      echo '\"';
	      echo $b;
	      //echo '\u0022';
	      echo '\"';
	      $jesx_cntChunkBytesDone += 4 + strlen($b);
	    } else {
	      echo '"';
	      echo $b;
	      echo '"';
	      $jesx_cntChunkBytesDone += 2 + strlen($b);
	    }
	    return true;
        } elseif (is_array($a)) {
	  $isList = true;
	  $isListStartingAt1 = false;
	  for ($i=0, reset($a); $i<count($a); $i++, next($a)) {
	      if (key($a) !== $i) { $isList = false; break; }
	  }
	  if (!$isList) {
	    //allow for numeric arrays starting at 1
	    $isList = true;
	    $isListStartingAt1 = true;
	    for ($i=1, reset($a); $i<=count($a); $i++, next($a))
		if (key($a) !== $i) { $isList = false; break; }
	  }
	  if ($isList) {
	      echo '[';
	      $jesx_cntChunkBytesDone += 1;
	      if ($isListStartingAt1) {
		if ($extraEscaping) {
		  echo '\"hmDeleteMe\",'; //so the receiving end starts at 1 too
		  $jesx_cntChunkBytesDone += 15;
		} else {
		  echo '"hmDeleteMe",'; //so the receiving end starts at 1 too
		  $jesx_cntChunkBytesDone += 13;
		}
	      }
	      $first = true;
	      foreach ($a as $v) {
		if ($first) { $first = false; } else { echo ',';  $jesx_cntChunkBytesDone += 1; }
		json_encode_safer_xxl_do ($v,$extraEscaping);
	      }
	      echo ']';
	      $jesx_cntChunkBytesDone += 1;
	  } else {
	      echo '{';
	      $jesx_cntChunkBytesDone += 1;
	      $first = true;
	      foreach ($a as $k=>$v) {
		  if ($k=='hmOverrides') {
		    if (is_array($v) && array_key_exists('jsonMe', $v)) {
		      if ($v['jsonMe'] == true) $extraEscaping = true;
		    }
		  }
		  if ($first) { $first = false; } else { echo ','; }
		  json_encode_safer_xxl_do ($k,$extraEscaping, true);
		  echo ':';
		  $jesx_cntChunkBytesDone += 1;
		  json_encode_safer_xxl_do ($v,$extraEscaping);
	      }
	      echo '}';
	      $jesx_cntChunkBytesDone += 1;
	  }
	}
//  ob_flush(); //flush the output buffer
  return true;
}

function json_encode_safer($a, $extraEscaping=false, $isKey=false) {
// outputs a single string of JSON, directly to the output buffer.
// but browsers, in January 2010, do not like strings > 60 megabyte. thats why _xxl was created.
  
//was formerly php_js() by php at koterov dot ru, 
// somewhat modified by rene7705@gmail.com
	if (is_null($a)) echo 'null';
        if ($a === false) echo 'false';
        if ($a === true) echo 'true';
	if (is_int($a) || is_float($a)) {
	  if ($isKey) {
	    if ($extraEscaping) {
	      echo '\"'.$a.'\"';
	    } else {
	      echo '"'.$a.'"';
	    }
	  } else {
	    echo $a;
	  }
	} else if (is_string($a)) {
	    $b = '';
	    if ($a=='') {
	      //if ($extraEscaping) echo '\"\"'; else echo '""';
	    } else {
	      $esc = '\\';
	      $skip = 0;
	      for ($i=0; $i<strlen($a); $i++) {
		if ($skip>0) {
		  $i += $skip;
		  if ($i>=strlen($a)) break;
		  $skip = 0;
		}
		$c = substr($a,$i,3);
		if (
		  $c=='\\u' ||
		  $c=='\\\\'
		) {
		  //skip!
		} elseif ($c=='-->') {
		  $c = '--|>'; //break HTML comment endings, coz it'll break the js decoding
		  $b.= $c;
		  $skip = 2;
		} else {
		  $c = substr($c, 0, 1);
		  if (
		    $c == ' ' || 
		    $c == '"' ||
		    $c == "'" ||
		    $c == "\t" ||
		    $c == "\n" || //TODO try
		    $c == "\r" ||
		    $c == ')' || 
		    $c == '(' || 
		    ( $c>='a' && $c<='z') ||
		    ( $c>='A' && $c<='Z') ||
		    ( $c>='0' && $c<='9') ||
		    $c == '.' || 
		    $c == '-' || 
		    $c == '_' || 
		    $c == '%' || 
		    $c == '!' || 
		    $c == '#' || 
		    $c == '$' || 
		    $c == '%' || 
		    $c == '&' || 
		    $c == '^' || 
		    $c == ',' || 
		    $c == ':' || 
		    $c == ';' || 
		    $c == '=' || 
		    $c == '?' || 
		    $c == '@' || 
		    $c == '`' || 
		    $c == '~' || 
		    $c == '|' || 
		    $c == '>' ||
		    $c == '<' ||
		    $c == '}' ||
		    $c == '{' ||
		    $c == ']' ||
		    $c == '[' ||
		    $c == '/' ||
		    $c == '+' ||
		    $c == '\\' 
		  ) {
		    //if ($c=="'") $c = '\\\'';
		    if ($c=='/') $c = '\\/';
		    elseif ($c=='\\') $c = '\\\\';
		    elseif ($c=='"') $c = '\\"';//$c= '~`';
		    elseif ($c=="\n") $c = '\\n';
		    elseif ($c=="\r") $c = '\\r';
		    elseif ($c=="\t") $c = '\\t';
		  } else {
		    $c = dechex(ord($c));
		    if (strlen($c)==1) $c= '000'.$c;
		    elseif (strlen($c)==2) $c= '00'.$c;
		    elseif (strlen($c)==3) $c= '0'.$c;
		    $c = $esc.'u'.$c;
		  }
		  $b.=$c;
		}
	      }
	    }	
	    if ($extraEscaping) {
	      //echo '\u0022';
	      echo '\"';
	      echo $b;
	      //echo '\u0022';
	      echo '\"';
	    } else {
	      echo '"';
	      echo $b;
	      echo '"';
	    }
	    return true;
        } elseif (is_array($a)) {
	  $isList = true;
	  $isListStartingAt1 = false;
	  for ($i=0, reset($a); $i<count($a); $i++, next($a)) {
	      if (key($a) !== $i) { $isList = false; break; }
	  }
	  if (!$isList) {
	    //allow for numeric arrays starting at 1
	    $isList = true;
	    $isListStartingAt1 = true;
	    for ($i=1, reset($a); $i<=count($a); $i++, next($a))
		if (key($a) !== $i) { $isList = false; break; }
	  }
	  if ($isList) {
	      echo '[';
	      if ($isListStartingAt1) {
		if ($extraEscaping) {
		  echo '\"hmDeleteMe\",'; //so the receiving end starts at 1 too
		} else {
		  echo '"hmDeleteMe",'; //so the receiving end starts at 1 too
		}
	      }
	      $first = true;
	      foreach ($a as $v) {
		if ($first) { $first = false; } else { echo ','; }
		json_encode_safer($v,$extraEscaping);
	      }
	      echo ']';
	  } else {
	      echo '{';
	      $first = true;
	      foreach ($a as $k=>$v) {
		  if ($k=='hmOverrides') {
		    if (is_array($v) && array_key_exists('jsonMe', $v)) {
		      if ($v['jsonMe'] == true) $extraEscaping = true;
		    }
		  }
		  if ($first) { $first = false; } else { echo ','; }
		  json_encode_safer($k,$extraEscaping, true);
		  echo ':';
		  json_encode_safer($v,$extraEscaping);
	      }
	      echo '}';
	  }
	}
//  ob_flush(); //flush the output buffer
  return true;
}

function json_encode_safe($a, $extraEscaping=false, $isKey=false) {
// returns a JSON string of $a to the calling function.  
  
//was formerly php_js() by php at koterov dot ru, 
// somewhat modified by rene7705@gmail.com
        if (is_null($a)) return 'null';
        if ($a === false) return 'false';
        if ($a === true) return 'true';
	if (is_int($a) || is_float($a)) {
	  if ($isKey) {
	    if ($extraEscaping) {
	      return '\"'.$a.'\"';
	    } else {
	      return '"'.$a.'"';
	    }
	  } else {
	    return $a;
	  }
	} else if (is_string($a)) {
	    $b = '';
	    if ($a=='') {
	      echo '""';
	    } else {
	      $esc = '\\';
	      $skip = 0;
	      for ($i=0; $i<strlen($a); $i++) {
		if ($skip>0) {
		  $i += $skip;
		  if ($i>=strlen($a)) break;
		  $skip = 0;
		}
		$c = substr($a,$i,3);
		if (
		  $c=='\\u' ||
		  $c=='\\\\'
		) {
		  //skip!
		} elseif ($c=='-->') {
		  $c = '--|>'; //break HTML comment endings, coz it'll break the js decoding
		  $b.= $c;
		  $skip = 2;
		} else {
		  $c = substr($c, 0, 1);
		  if (
		    $c == ' ' || 
		    $c == '"' ||
		    $c == "'" ||
		    $c == "\t" ||
		    $c == "\n" || 
		    $c == "\r" ||
		    $c == ')' || 
		    $c == '(' || 
		    ( $c>='a' && $c<='z') ||
		    ( $c>='A' && $c<='Z') ||
		    ( $c>='0' && $c<='9') ||
		    $c == '.' || 
		    $c == '-' || 
		    $c == '_' || 
		    $c == '%' || 
		    $c == '!' || 
		    $c == '#' || 
		    $c == '$' || 
		    $c == '%' || 
		    $c == '&' || 
		    $c == '^' || 
		    $c == ',' || 
		    $c == ':' || 
		    $c == ';' || 
		    $c == '=' || 
		    $c == '?' || 
		    $c == '@' || 
		    $c == '`' || 
		    $c == '~' || 
		    $c == '|' || 
		    $c == '>' ||
		    $c == '<' ||
		    $c == '}' ||
		    $c == '{' ||
		    $c == ']' ||
		    $c == '[' ||
		    $c == '/' ||
		    $c == '+' ||
		    $c == '\\' 
		  ) {
		    //if ($c=="'") $c = '\\\'';
		    if ($c=='/') $c = '\\/';
		    elseif ($c=='\\') $c = '\\\\';
		    elseif ($c=='"') $c = '\\"';//$c= '~`';
		    elseif ($c=="\n") $c = '\\n';
		    elseif ($c=="\r") $c = '\\r';
		    elseif ($c=="\t") $c = '\\t';
		  } else {
		    $c = dechex(ord($c));
		    if (strlen($c)==1) $c= '000'.$c;
		    elseif (strlen($c)==2) $c= '00'.$c;
		    elseif (strlen($c)==3) $c= '0'.$c;
		    $c = $esc.'u'.$c;
		  }
		  $b.=$c;
		}
	      }
	    }	
	    if ($extraEscaping) {
	      return '\"'.$b.'\"';
	    } else {
	      return '"'.$b.'"';
	    }
	    
        }
	
        $isList = true;
	$isListStartingAt1 = false;
        for ($i=0, reset($a); $i<count($a); $i++, next($a))
            if (key($a) !== $i) { $isList = false; break; }
	if (!$isList) {
	  //allow for numeric arrays starting at 1
	  $isList = true;
	  $isListStartingAt1 = true;
	  for ($i=1, reset($a); $i<=count($a); $i++, next($a))
	      if (key($a) !== $i) { $isList = false; break; }
	}
        $result = array();
        if ($isList) {
	      if ($isListStartingAt1) {
		if ($extraEscaping) {
		  $result[] = '\"hmDeleteMe\"'; //so the receiving end starts at 1 too
		} else {
		  $result[] = '"hmDeleteMe"'; //so the receiving end starts at 1 too
		}
	      }
	      foreach ($a as $v) 
		  $result[] = json_encode_safe($v,$extraEscaping);			
	      return '[' . join(',', $result) . ']';
        } else {
            foreach ($a as $k=>$v)
                $result[] = json_encode_safe($k,$extraEscaping, true) . ':' . json_encode_safe($v,$extraEscaping);
            return '{' . join(',', $result) . '}';
        }
}


// ---
//      self-test functions:

function htmlMicroscope_selfTest ($p, $q) {
  set_time_limit(0);
// defaults for parameters;
  $mem = 130; // memory limit in Mb, 10 minimum
  $grace = 4; // how much Mb to stay under the memory limit
  $duration = -1; // max execution time
  $keys = 999999999; // i'd rather specify how much memory to use.
  $deep = 7;
  $addStrangeDataTypes = !array_key_exists('nosdt', $_GET);
  if ($addStrangeDataTypes) $grace+=8;
  $themeOverride = true;

// possibly override params from url-commandline
  if (array_key_exists('mem', $_GET) && is_numeric($_GET['mem'])) {
    $mem = (int)$_GET['mem'];
  }
  if (array_key_exists('grace', $_GET) && is_numeric($_GET['grace'])) {
    $grace = (int)$_GET['grace'];
  }
  if (array_key_exists('duration', $_GET) && is_numeric($_GET['duration'])) {
    $duration = (int)$_GET['duration'];
  }
  if (array_key_exists('keys', $_GET) && is_numeric($_GET['keys'])) {
    $keys = (int)$_GET['keys'];
  }
  if (array_key_exists('deep', $_GET) && is_numeric($_GET['deep'])) {
    $deep = (int)$_GET['deep'];
  }
  if (array_key_exists('themeOverride', $_GET) ) {
    $themeOverride = $_GET['themeOverride'];
		if ($themeOverride=='false') $themeOverride=false;
  }
  $newMem = ini_set('memory_limit', $mem.'M');
  echo "\n".'<!-- ';
  if ($newMem!==false) {
    echo "\n\t\t".'htmlMicroscope self-test; changed memory limit for this run to '.$mem.'Mb';
  } else {
    echo "\n\t\t".'htmlMicroscope self-test; could not change memory limit for this run from '.ini_get('memory_limit').' to '.$mem.'Mb';
  }
  echo "\n\t\t\t".'Will use no more than approx '.($mem-$grace).'Mb';
  echo "\n".' -->';
  echo "\n";
  define ('MEMORY_AVAILABLE', ($mem-$grace) * 1024 * 1024); // in bytes
  define ('DURATION', ($duration==-1?-1:$duration * 60)); // in seconds. -1 = no time limit



// start generating
  $test = array();
  
  if ($addStrangeDataTypes) {
      $asciiTable='';
      for ($i=1; $i<hexdec('ff'); $i++) {
				$asciiTable.=chr($i).' ';
      }
      
      $unicodeTable = '';
      for ($i=1; $i<hexdec('ffff'); $i++) {
				$unicodeTable.=unichr($i).' ';
      }
      
      $jsonInKey = json_encode_safe(array(
				'check' => array('this'=>'out')
      ));
      
      $test['All ASCII'] = array('here'=>$asciiTable);
      $test['All Unicode'] = array ('here'=>$unicodeTable);
      
      $test['some HTML'] = array(
				'hmOverrides' => array (
				  'keyAsPre' => true,
				  'valRenderHTML' => true
				),
				'credits' => 'http://www.immigration-usa.com/html_colors.html',
				'hit "<html>"!' => file_get_contents('testdata.html')
      );
      
      $test['JSON data'] = array (
				'here' => json_encode_safe(array(
				    'we'=>'go',
				    '...'=>array(
				    'deeper' => array(
				      'and' => array (
					'deeper' => array (
					  'down' => array(
					    'the' => array(
					      'rabbit' => 'hole',
					      //'html within json' => array('here'=>file_get_contents('testdata.html')),
					      'ASCII' => array('here'=>$asciiTable),
					      //'Unicode' => array('here'=>$unicode)
      )))))))));
      
      $test['img as key'] = array (
				'hmOverrides' => array(
				  'keyRenderHTML' => true
				),
				'<div style="width:100%;height:100%;color:white;font-size:120%;font-weight:bold;background:url(bg.gif) repeat;">key with backdrop;</div>' => 'xyz',
      );

      $test['json in key, theme override in sub'] = array(
			$jsonInKey => array (
			  'normal' => 'abc',		  
			  'theme override' => array ( 
			    'here' => htmlMicroscope_generateRandomArray(30,5, DURATION, MEMORY_AVAILABLE))
			  )
      );    
      $test['json in key, theme override in sub'][$jsonInKey]
			['theme override']['here']['hmOverrides'] = array(
			  'themeName' => 'renesRed'
      );
  };

  if ($themeOverride) {
		$test['theme override'] = htmlMicroscope_generateRandomArray(
				//$keys, $deep, DURATION, MEMORY_AVAILABLE
				200, 7, DURATION, MEMORY_AVAILABLE
		);
		$test['theme override']['keys'] = $keys;
    $test['theme override']['hmOverrides'] = array(
      'themeName' => 'renesRed2'
    );
	}

	
	$test['random'] = htmlMicroscope_generateRandomArray(
		$keys, $deep, DURATION, MEMORY_AVAILABLE
	);

  
  //svar_dump ($data);
  file_put_contents ('countdown.txt', 'done');
  hm ($test, 'example array');
  $test = null;
}


global $hmGenKeys;
$hmGenKeys = 0;
global $hmGenKeysDone;
$hmGenKeysDone = 0;
function htmlMicroscope_generateRandomArray ($maxKeys, $maxDepth, $maxDuration=-1, $maxMem=-1) {
  global $hmGenKeys;
  global $hmGenKeysDone;
  
  $r = array();
  $l1 = false;
  if ($maxKeys!==null) {
    $hmGenKeys = $maxKeys;
    $l1 = true;
  }
  
  $hmGenKeys--;
  if ($hmGenKeys<=0) return false;
  if ($maxDepth<=0) return false;
  if ($l1) {
    srand(htmlMicroscope_randMakeSeed());
    while ($hmGenKeys > 0) {
	$hmGenKeys--;
	$hmGenKeysDone++;
	file_put_contents('countdown.txt', 
	    'k:'.number_format($hmGenKeysDone,0,'.',',').
	    ' m:'.number_format(memory_get_usage(true),0,'.',',')
	);
	if ($maxMem!=-1 && memory_get_usage(true) > $maxMem) {echo"yea"; return $r;}
	if ($maxDuration!=-1 && $maxDuration < getDuration()) return $r;

	switch (rand(1,2)) {
	  case 1 : 
	    $next = htmlMicroscope_generateRandomArray (null, $maxDepth-1, $maxDuration, $maxMem);
	    if ($next!==false) 
	      $r +=  array(
		htmlMicroscope_randomValue(4) => $next
	      );
	    break;
	  case 2 :
	    $r += array(
	      htmlMicroscope_randomValue(4) => htmlMicroscope_randomValue(20)
	    );
	    break;
	}
    }
  } else {
    $range = rand(0,50);
    for ($i=0; $i<$range; $i++) {
	$hmGenKeys--;
	$hmGenKeysDone++;
	file_put_contents('countdown.txt', 
	    'k:'.number_format($hmGenKeysDone,0,'.',',').
	    ' m:'.number_format(memory_get_usage(true),0,'.',',')
	);
	if ($maxMem!=-1 && memory_get_usage(true) > $maxMem) return $r;
	if ($maxDuration!=-1 && $maxDuration < getDuration()) return $r;

	switch (rand(1,2)) {
	  case 1 : 
	    $next = htmlMicroscope_generateRandomArray (null, $maxDepth-1, $maxDuration, $maxMem);
	    if ($next!==false) 
	      $r +=  array(
		htmlMicroscope_randomValue(4) => $next
	      );
	    break;
	  case 2 :
	    $r += array(
	      htmlMicroscope_randomValue(4) => htmlMicroscope_randomValue(20)
	    );
	    break;
	}
    }
  } 
  
  if (($hmGenKeysDone/7919)==round($hmGenKeysDone/7919)) sleep(1);
    
  return $r;
}

function htmlMicroscope_randomValue($maxLength) {
  $r = '';
  switch (rand(0,9)) {
    case 0 : $r = rand (0,100000000); break;
    case 1 : $r = rand (0,100000000) / rand(1,100) / 3; break;
    default:
	switch (rand(0,1)) {
	  case 0:
	  $rnd = rand(1,$maxDepth);
	    for ($i = 0; $i < $rnd; $i++) {
	      $r.= unichr(rand(0,hexdec('ffff')));
	    }
	    break;
	  case 1: 
	    for ($i = 0; $i < $maxLength; $i++) {
	      $r.=chr(rand(ord('a'),ord('z')));;
	    }
	    break;
	}
	break;
  }
  //echo $r.'<br/>'.$maxLength.'<br/>';
  return $r;
}

function htmlMicroscope_randMakeSeed() {
  list($usec, $sec) = explode(' ', microtime());
  return (float) $sec + ((float) $usec * 100000);
}

/*
function htmlMicroscope_dumpDirect ($var, $title, $options=null, $hmSettings=null) {
  if (!$hmSettings) $hmSettings = htmlMicroscope_config();
  $id = preg_replace('/\s/','',getDuration());
  $id = preg_replace('/\./','_', $id);
  $htmlID = 'debug_'.$id;
//htmlDump ($var);

//  $data = json_encode_safe(json_prepare($var),true);

  $options = ($options ? json_encode_safe(json_prepare($options),true) : null);
  $traceData = htmlMicroscope_filterTrace(debug_backtrace(), array());
  $trace = array_merge(array(
      'hmOverrides' => array (
	'themeName' => '--trace--',
	'urlEditor' => $hmSettings['urlEditor']
       ),
       'traceData' => $traceData
  ));
  //htmlDump ($trace, "td2");
  echo '<div id="'.$htmlID.'" class="htmlMicroscope hm hmPreInit">';
    echo '<div id="'.$htmlID.'_hmPreInit" class="htmlMicroscope hm hmPreInit">';
      echo '<a href="http://mediabeez.ws/htmlMicroscope/">htmlMicroscope</a> ';
      echo '<span id="'.$htmlID.'_titleSpan">'.$title.'</span> ';
      echo '<br/><br/>';
      if (2==1) {
	$b = strlen(serialize($var)); //i suspect serialize to be slow and prone to memory hogging.
	echo '<span id="'.$htmlID.'_dataSize">'.$b.' bytes, '.filesizeHumanReadable($b).' of data to parse</span><br/><br/>';
      } else {
	echo '<span id="'.$htmlID.'_dataSize">Unknown size of bytes left to parse.</span><br/><br/>';
      }
      echo '<div id="'.$htmlID.'_preInitStatus" class="hm hmPreInitStatus" style="display:none">';
      echo '<span id="'.$htmlID.'_longMsg"> </span><br/><br/>';
      echo '<span id="'.$htmlID.'_shortMsg"> </span><br/><br/>';  
    echo '</div>';
    echo '<div id="'.$htmlID.'_data" style="display:none"><!-- ';
      json_encode_safer (json_prepare($var), false);
    echo ' --></div>';    
  echo '</div>';
  echo '</div>';
  echo '<script type="text/javascript" language="javascript">';
  echo '<!-- '."\n";
  echo 'var hmData = {';
  echo ' "title" : "'.$title.'", ';
  echo ' "date" : "'.date('r').'",';
  echo ' "time" : "'.getDuration().'",';
  echo ' "options" : '.($options?'"'.$options.'"':'null').', ';
  echo ' "trace" : "';
  json_encode_safer (json_prepare($trace), true);
  echo '", ';
  echo ' "id" : "'.$htmlID.'", ';
  echo ' "dataOrigin" : "php"';
  echo '};'."\n";
  echo 'rajmv.htmlMicroscope.process (hmData); '."\n";
  echo '-->'."\n";
  echo '</script>'."\n";
  return $r;
}
*/

?>
