<?
//*************************************************************************************************************************************/
//
// фукции вывода массивов и объектов на экран в удобной форме
//
//*************************************************************************************************************************************/

  function  print_rbr($arr)
  {
    echo nl2br(print_r($arr,true)) ;
  }

  // вывод двухмерного массива
  function print_2x_arr($arr=array(),$options=array())
	{ if (!is_array($options)) { $title=$options ; $options=array() ; }
      if (!isset($options['no_show_index'])) $options['no_show_index']=0 ;
      if (_sizeof($arr))
      { ?><table class="basic fz_small left debug print_2x_arr tablesorter <?echo $options['table_class']?>"><thead><?
        // собираем все ключи всех таблиц
        $sum_titles=array() ;
        foreach ($arr as $finfo) if (_sizeof($finfo)) $sum_titles=array_merge($sum_titles,array_keys($finfo)) ; else $sum_titles=array() ;
        // удаляем повторяющеся поля
        $ftitles=array_unique($sum_titles) ;

        if ($title) echo '<tr class=clss_header><td colspan='.(_sizeof($ftitles)+1).'>'.$title.'</td><tr>' ;
        echo '<tr class=td_header>' ;
        if (!$options['no_show_index']) echo '<th>№</th>' ;
        foreach ($ftitles as $title) echo '<th>'.$title.'</th>' ; ?></tr></thead><tbody><?
        $clss=0 ; $i=1 ;
        foreach ($arr as $fname=>$finfo)
         {  if ($finfo['clss'])
            { $clss=$finfo['clss'] ;

            }
            ?><tr>
              <?if (!$options['no_show_index']){?><td><? echo ($options['show_index_num'])? $i:$fname?></td><?}
           	  foreach ($ftitles as $title)
              { $value=$finfo[$title] ;
                //echo '$options[$title]='.$options[$title].'<br>' ;
                if (($title==='c_data' or $title==='r_data' or $title==='e_data' or strpos($title,'time_')!==false) and !$options['no_view_date']) $value=($value>0)? date('d.m.Y H:i:s',$value):'' ;
                if ($options[$title]==='timedata')         $value=date('d.m.Y H:i:s',$value) ;
                ?><td><? if (is_array($finfo[$title])) print_1x_arr($finfo[$title]) ;
                         else if (!is_object($finfo[$title]))
                         {   if ($options['show_serialize_fields_as_array'] and $clss and _CLSS($clss)->fields[$title]=='serialize') damp_array(unserialize($value),1,-1) ;
                             //else echo htmlentities($value) ;
                             else echo ($value) ;
                         }
                         else { echo 'Объект класса ' ; }
                  ?></td><?

              }
            ?></tr><?
            $i++ ;
         }
        ?></tbody></table><?
      } else echo 'array()<br/>';
	}

 function print_1x_arr($arr=array(),$options=array())
	{ if (_sizeof($arr))
      { ?><table class="left debug print_1x_arr"><?
        foreach ($arr as $fname=>$finfo) print_key_value($fname,$finfo,$options) ;
        ?></table><?
      } else echo 'array()<br/>';
	}

 function print_key_value($fname,$finfo,$options=array())
         { ?><tr><td><? echo $fname?></td><td><?
                 if (is_array($finfo))
          { if ($fname==='data' and isset($finfo[0]['x']) and isset($finfo[0]['y']) and isset($finfo[0]['t'])) echo 'Оцифровка подписи, '._sizeof($finfo).' значений' ;
                   elseif ($fname==='frames') echo 'Фреймы facecontrol, '._sizeof($finfo).' позиций' ;
                   else print_1x_arr($finfo,$options) ;
                 }
          else if (is_bool($finfo)) echo ($finfo)? 'true':'false' ;
                 else if (is_object($finfo)) { if (get_class($finfo)=='stdClass') damp_array($finfo,1,-1) ;
                                               else echo 'Объект "'.get_class($finfo).'"'  ;/*else print_r($finfo) ;*/
                                              }
                 else
                 {   $show_short_view=0 ;
                     if (stripos($finfo,'data:image')!==false) {?><img width=150 alt="" src="<?echo $finfo?>"  alt=""><? $show_short_view=1 ;}
              else if (strlen($finfo)<=1000 or $fname==='debug_db') echo ($finfo) ;
                     else if (base64_decode($finfo, true)) {?><img alt=""  width=150  src="data:image/jpeg;base64,<?echo $finfo?>"><?}
                     else $show_short_view=1 ;

              if ($show_short_view) {?><textarea wrap="soft" class="<?if (!$options['no_short_view']) echo 'short_view'?>" style="display:block;border:1px solid #aaaaaa;padding:3px;width:95%;height:200px;font-size:10px;"><? echo ($finfo) ?></textarea><?}
              //echo '<br>['.strlen($finfo).'] '.$fname ;
                 }
            ?></td></tr><?
         }

 function get_damp_array($arr,$mode=1,$show_trace=-1)
 { ob_start() ;
   damp_array($arr,$mode,$show_trace) ;
   $text=ob_get_clean() ;
   return($text) ;
 }

 // $mode = 1: выводить массивы через 1x, =2: выводить массивы через 2x
 // damp_array($arr,1,-1) - вывести массив для любого IP без трассировки
 function damp_array($arr,$mode=1,$show_trace=1,$options=array())
 { if (!_IS_SYSTEM_IP and _ENGINE_MODE!='admin' and $show_trace!=-1) return ;
   if (_sizeof($arr))
   { if ($show_trace>0) print_info_sender_function($show_trace) ;
     ?><table class="left debug damp_array"><?
     if ((is_array($arr) or is_object($arr)) and _sizeof($arr))
     { // var_dump($arr) ;
       foreach ($arr as $key=>$value)
       {   if (!(is_object($value) and $key==='system')) /// импользовать именно === иначе 0 = system
           {  if (!is_array($value) and !is_object($value)) print_key_value($key,$value,$options) ;
  		else // значение - массив
      { ?><tr><?
                $value1=reset($value) ;
          if (!is_array($value1)) { ?><td><strong><? echo $key ; ?></strong></td><td><? print_1x_arr($value,$options) ; ?></td><? }  // если массив состоит из строк - выводим его
          else
                { $value2=reset($value1) ;
           	if (!is_array($value2)) { ?><td><strong><? echo $key ; ?></strong></td><td><? if ($mode==1) print_1x_arr($value,$options) ; else print_2x_arr($value) ;?></td><? }
                    else { ?><td><strong><? echo $key ; ?></strong></td><td><? damp_array($value,$mode,-1) ; ?></td><? }
		}
		?></tr><?
	  }

	  }
      else
      {
            ?><tr><td><? echo $key ; ?></td><td><? if (is_object($value)) echo 'object "<strong>'.get_class($value).'"</strong> ['._sizeof($arr) ; ?>]</td></tr><? ;
           }
      }
     }
 	 ?></table><?
   }
 }

 function damp_string($str)
 { $arr2=array() ;
   $arr=str_split($str) ;
   if (_sizeof($arr)) foreach($arr as $i=>$ch) $arr2[$i]=array($ch,ord($ch)) ;
   print_2x_arr($arr2) ;
  return($arr2) ;
 }

 function print_info_sender_function($trace_level=3)
 { global $debug_trace_level ;
   if (!$debug_trace_level) $debug_trace_level=$trace_level ;
   $arr_trace=debug_backtrace() ;
   $all_levels=_sizeof($arr_trace) ;
   if ($debug_trace_level=='all') $from_level=$all_levels ;
   else    						  $from_level=($debug_trace_level>$all_levels)? $all_levels:$debug_trace_level+1 ;
   if ($from_level) for ($i=$from_level; $i>0; $i=$i-1) //if (strpos($arr_trace[$i-1]['file'],'i_db.php')===false)
   //echo '<div class=small>function <strong>'.$arr_trace[$i]['function'].'()</strong> '.str_replace(_DIR_TO_ROOT.'/','/',$arr_trace[$i-1]['file']).':'.$arr_trace[$i-1]['line'].'</div>' ;
   echo '<div class=small>function <strong>'.$arr_trace[$i]['function'].'()</strong> '.str_replace(_DIR_TO_ROOT.'/','/',$arr_trace[$i]['file']).':'.$arr_trace[$i]['line'].'</div>' ;
   echo '-------------<br>' ;

   //echo '<div class=small>function <strong>'.$arr_trace[3]['function'].'()</strong> '.str_replace(_DIR_TO_ROOT.'/','/',$arr_trace[2]['file']).':'.$arr_trace[2]['line'].'</div>' ;
   //echo '<div class=small>function <strong>'.$arr_trace[2]['function'].'()</strong> '.str_replace(_DIR_TO_ROOT.'/','/',$arr_trace[1]['file']).':'.$arr_trace[1]['line'].'</div>' ;

 }

 function print_SQL_debug_begin($sql)
 {  global $debug_db,$__debug_sql_cnt ;
    ?><div style="border:1px solid black;margin:5px;padding:5px;BACKGROUND-COLOR: #F9F9F7;color:black;"><?
    if ($debug_db==2) print_info_sender_function() ;
    ?><span class='red bold'><?echo $__debug_sql_cnt+1 ;?>. </span><?
	echo nl2br($sql).'&nbsp;<i class="fa fa-line-chart v2" cmd="db/explain_sql" sql="'.base64_encode($sql).'" aria-hidden="true"></i><br>' ;
 }

 function print_SQL_debug_end() { ?></div><?}

 function print_error($text)
 { if (!_IS_SYSTEM_IP) return ;
   print_info_sender_function() ;
   //$arr_trace=debug_backtrace() ;
   //echo '<div class=small>Место: '.str_replace(_DIR_TO_ROOT.'/','/',$arr_trace[0]['file']).':'.$arr_trace[0]['line'].' - function <strong>'.$arr_trace[1]['function'].'()</strong></div>' ;
   echo '<div class=alert>'.$text.'</div>' ;
 }

 function print_array(&$arr=array(),$title='Заголовок таблицы')
	{ if (_sizeof($arr))
      { ?><div>
        <style>
		.pa_table{BORDER-left: #F3ECDD 1px solid;}
		td{font-family: tahoma,verdana,arial;font-size: 11px;color: Black;}
		.pa_header{FONT-SIZE: 12px;COLOR: #23598c;background: #FFFDE8;font-weight: bold;FONT-FAMILY: Tahoma ;vertical-align: middle;
						 PADDING: 5px; BORDER-TOP: #DDE1E4 1px solid;BORDER-BOTTOM: #DDE1E4 1px solid;BORDER-LEFT: #DDE1E4 0px solid; BORDER-RIGHT: #DDE1E4 1px solid;
						}
        td.pa_data{	BORDER-TOP: white 0px solid;BORDER-BOTTOM: #F3ECDD 1px solid;   BORDER-LEFT: white 1px solid;	BORDER-RIGHT: #F3ECDD 1px solid;	text-align: center;	color: black ;	 background: #f9f9f7 ;	PADDING: 2px;height: 22px;}
        td.pa_l_data{BORDER-TOP: white 0px solid;BORDER-BOTTOM: #F3ECDD 1px solid;   BORDER-LEFT: white 1px solid;	BORDER-RIGHT: #F3ECDD 1px solid;	text-align: left;	color: black ;	 background: #f9f9f7 ;	PADDING: 2px;height: 22px;}
        </style>
        <table class='pa_table' style='valign:top' cellspacing=0 cellpadding=0><?
        $inf=each($arr) ;
        if (is_array($inf[1])) $ftitles=array_keys($inf[1]) ;
        reset($arr) ;
        echo '<tr><td class=pa_header colspan=100>'.$title.'</td><tr>' ;
        if (is_array($inf[1])) { echo '<tr><td class=pa_data>&nbsp;</td>' ; foreach ($ftitles as $title) echo '<td class=pa_data>'.$title.'</td>' ; echo '</tr>' ; }
        foreach ($arr as $fname=>$finfo)
         { echo '<tr><td class=pa_l_data>'.$fname.'</td>' ;
           if (is_array($finfo) and _sizeof($ftitles)) foreach ($ftitles as $title) if (!is_array($finfo[$title])) echo '<td class=pa_l_data>'.$finfo[$title].'</td>' ; else { echo '<td class=pa_l_data>' ; print_r($finfo[$title]) ; echo '</td>' ; }
            else echo '<td class=pa_l_data>'.$finfo.'</td>' ;
           echo '</tr>' ;
         }
        ?></table></div><?
      }
      echo '<br>' ;
	}


  function echo_var($var)
	{ if (!_IS_SYSTEM_IP) return ;
      echo $var ;
	}


//*************************************************************************************************************************************/
//
// фукции отладки
//
//*************************************************************************************************************************************/

 function trace($mode=0,$level=0)
	  { //ob_start();
	    echo '<h1>Трассировка вызова функций</h1>' ;
	    $arr=debug_backtrace() ;
	    unset($arr[0]) ;
        if ($level) $arr=array_slice($arr,0,$level) ;
	    print_2x_arr($arr) ;
	    //damp_array(debug_backtrace()) ;
	    if ($mode){ echo '<h1>Список подключенных файлов</h1>' ;
	    			print_1x_arr(get_included_files()) ;
	    		  }
	    //$out = ob_get_clean();
	    //return($out) ;

	    echo '<strong>Дамп отладки:</strong><br>' ;
	    global $debug_info ;
	    if (_sizeof($debug_info)) damp_array($debug_info) ;

	  }

 // показ информации по ошибке
 // $text - текст сообщения
 // сколько уровней показывать
 // какой уровень показывать (будет показан тока один уровень)
 function damp_error($text='',$show_levels=0,$show_count=0)
 	  { echo $text.'<br>' ;
 	    $arr=debug_backtrace() ; //unset($arr[0]) ;
 	    echo '<strong>Дамп программы:</strong><br>' ;
 	    if (!$show_levels) $show_levels=_sizeof($arr) ;
 	    if (_sizeof($arr)) foreach($arr as $i=>$rec) if ($i and $i<=$show_levels and ($show_count==0 or $show_count==$i))
        if ($rec['function']!='SQL_error_message' and $rec['function']!='trigger_error' and $rec['function']!='userErrorHandler' and $rec['function']!='get_trace_info' and $rec['function']!='register_SQL_long_to_db' and $rec['function']!='debug_db_logging' and $rec['function']!='register_SQL_error_to_db')
	    {  echo '<hr><strong>Файл:'.$rec['file'].':'.$rec['line'].'</strong>&nbsp;&nbsp;&nbsp;' ;
	       if ($rec['class']) echo '<span style="color:green;">'.$rec['class'].'</span>' ;
	       if ($rec['type']) echo $rec['type'] ;
	       echo '<span style="color:green;font-weight:bold;">'.$rec['function'].'</span><br>' ;
	       //if (_sizeof($rec['args']))
	       damp_array($rec['args'],1,-1); '<br><br>' ;
	       //echo nl2br(print_r($rec['args'])) ;
	    }
	    echo '<strong>Дамп отладки:</strong><br>' ;
	    global $debug_info ;
	    if (_sizeof($debug_info)) damp_array($debug_info,1,-1) ;

 	  }


  // функция для фиксирования временных интервалов выполения кода
  // $time_before=fixed_time() ; - фиксируем время перед вызов функции в переменной $time_before
  // fixed_time($time_before,'запрос к БД занял - ','') ; - выводим время, прошедшее от момента $time_before,
  //   если $title>'' выводим сообщение "запрос к БД занял - ",
  //   строку после сообщения не переводим
  //   если $time_before=0, возвращаем текущее время
  //   если $time_before>0, возвращаем разницу времен

  function fixed_time($querytime_begin=0,$title='')
  {  list($usec, $sec) = explode(' ', microtime());
     $querytime_now = ((float)$usec + (float)$sec);
     $querytime_delta = $querytime_now - $querytime_begin;
     if ($title) echo sprintf('<div>'.$title.'<span style="color:green;font-weight:bold"> %01.4f сек</span></div>',$querytime_delta) ;
     if (!$querytime_begin) return($querytime_now) ; else return($querytime_delta) ;
  }


 function get_formatted_microtime() {
   list($usec, $sec) = explode(' ', microtime());
   return $usec + $sec;
}

 function set_time_point($title)
 { global $__times,$__memory ;
   $__times[$title]=get_formatted_microtime() ;
   if (function_exists('memory_get_usage'))  $__memory[$title]=round(memory_get_usage()/1024) ;
 }

 function show_time_line($mode=1,$text='',$show_from='')
 { global $__times,$__memory,$debug ;
   if (!$text) $text='Время генерации страницы:' ;
   $alt_time=0 ; $start=0 ;
   //damp_array($__times,1,-1) ;
   $sum_time=$__times['end']-$__times['start'] ;
   if ($debug or $mode>=2)
   {   $ff=0 ;
	   if (_sizeof($__times)) foreach ($__times as $info=>$time)
	     { $delta=($alt_time)? round($time-$alt_time,6):0 ;
           $proc=round($delta/$sum_time*100,2) ;
	       if (!$alt_time) $start=$time ;
	       $ff=(!$show_from or $ff or $info==$show_from)? 1:0;

           $micro = sprintf("%06d",($time - floor($time)) * 1000000);
           $d = new DateTime( date('Y-m-d H:i:s.'.$micro, $time) );



	       if ($ff)
           {  $rec=array('Время'=>$d->format("Y-m-d H:i:s.u"),
                         'Операция'=>$info,
                         'Время выполнения'=>'+'.number_format($delta, 6, '.', ' '),//printf('%01.1f',$delta), //round($delta,6).'с.',
                         '%'=>round($proc).' %', ///printf('%01.1f',$proc).'%',
                         'Суммарное время'=>number_format(($time-$start), 6, '.', ' ').'с.',
                         'Память'=>$__memory[$info],
                   )  ;
               $recs[]=$rec ;
           }
	       $alt_time=$time ;
	     }
	   print_2x_arr($recs) ;
	   ?><script type=text/javascript>window.document.title=window.document.title+' <?echo round($time-$start,6)?> с.' ;</script><?

   } else echo '<div style="font-family:arial;font-size:12px;text-align:left;">'.$text.' '.round($__times['end']-$__times['start'],6).' c.</div>'  ;
 }

 function alert_SQL_inject()
 { $mess=get_script_info() ;
   _send_mail(_EMAIL_ENGINE_ALERT,'Попытка взлома сайта путем SQL иньекции '._BASE_DOMAIN.' c IP '.IP,$mess,array('debug'=>0,'no_reg_events'=>1,'Content-type'=>'text/html')) ;
   if (_IS_SYSTEM_IP) echo '<div class=alert>В условиях запроса присутствуют элементы SQL-иньекции: слова select,from,where</div><br>' ;
 }



function userErrorHandler($errno,$errmsg,$filename,$linenum,$vars='')
{ //global $send_mail_by_error ;
  //if (!$send_mail_by_error) return ;
  if ($errno==8) return ;
  $errmsg=hide_server_dir($errmsg) ;
  $filename=hide_server_dir($filename) ;
  if (strpos($errmsg,'is deprecated')!==false) return ;
  if (strpos($errmsg,'should be compatible')!==false) return ;
  echo $filename.'('.$linenum.'):'.$errmsg."\n\n"  ;
  return(1) ;
}

function register_SQL_error_to_db($errno,$errmsg)
{  global $SF_REQUEST_URI ;
   if (isset($GLOBALS['register_SQL_error_to_db']) and $GLOBALS['register_SQL_error_to_db']==1) return(0) ; // предотвращение зацикливания
   $GLOBALS['register_SQL_error_to_db']=1 ;
   if (!isset($_SESSION['pkey_by_table'][TM_LOG_SQL_ERRORS])) return(0) ;   // если таблицы нет - выход
   $trace_fname=LOGS()->reg_file_log('error_trace',get_trace_info()) ;
   $rec=array('indx'=>1,
              'clss'=>51,
              'IP'=>IP,
              'account_id'=>(MEMBER()->id)? MEMBER()->id:0,
              'typ'=>$errno,
              'obj_name'=>base64_encode($errmsg),
              'url'=>substr($_SERVER['HTTP_HOST'].$SF_REQUEST_URI,0,254),
              'trace'=>$trace_fname
   ) ;
   $id=adding_rec_to_table_fast(TM_LOG_SQL_ERRORS,$rec) ;
   $GLOBALS['register_SQL_error_to_db']=0 ;
   return($id) ;
}

function register_SQL_long_to_db($sql,$time_exec,$time_work,$count)
{  global $SF_REQUEST_URI ;
   if (isset($GLOBALS['register_SQL_long_to_db']) and $GLOBALS['register_SQL_long_to_db']==1) return(0) ; // предотвращение зацикливания
   $GLOBALS['register_SQL_long_to_db']=1 ;
   if (!isset($_SESSION['pkey_by_table'][TM_LOG_SQL_LONG])) return(0) ;  // если таблицы нет - выход
   $trace_fname=LOGS()->reg_file_log('SQL_long_trace',get_trace_info(array('explain_sql'=>$sql))) ;
   $rec=array('indx'=>1,
              'clss'=>79,
              'IP'=>IP,
              'account_id'=>(MEMBER()->id)? MEMBER()->id:0,
              'obj_name'=>base64_encode($sql),
              'url'=>substr($_SERVER['HTTP_HOST'].$SF_REQUEST_URI,0,254),
              't_exec'=>$time_exec,
              't_send'=>$time_work,
              'cnt'=>($count)?:0,
              'trace'=>$trace_fname,
              'server_ip'		=>	$_SERVER['SERVER_ADDR'],
              'db_node'		=>	(int)getenv('NODE_ID'),

   ) ;
   $id=adding_rec_to_table_fast(TM_LOG_SQL_LONG,$rec) ;
   $GLOBALS['register_SQL_long_to_db']=0 ;
   return($id) ;
}

function get_trace_info($options=array())
{  ob_start() ;
   if ($options['explain_sql'] and stripos($options['explain_sql'],'insert')===false and stripos($options['explain_sql'],'update')===false and stripos($options['explain_sql'],'delete')===false and stripos($options['explain_sql'],'replace')===false)
   {  ?><h2>EXPLAIN SQL</h2><?
      echo $options['explain_sql'].'<br>' ;
      $res=execSQL('EXPLAIN '.$options['explain_sql']) ;
      print_2x_arr($res) ;
   }

   ?><h2>TRACE</h2><?
   damp_error() ;
   ?><h2>SERVER</h2><?
   damp_array($_SERVER,1,-1) ;
   ?><h2>$_POST</h2><?
   damp_array($_POST,1,-1) ;
   ?><h2>$_GET</h2><?
   damp_array($_GET,1,-1) ;
   ?><h2>$_FILES</h2><?
   damp_array($_FILES,1,-1) ;
   $text=ob_get_clean() ;
   return($text) ;

}

function get_script_info($filename='',$linenum=0,$errno=0)
 { global $SF_REQUEST_URI ;
   $errortype = array(1    => "Error",2    => "Warning",4    => "Parsing Error",8    => "Notice",16   => "Core Error",32   => "Core Warning",64   => "Compile Error",128  => "Compile Warning",256  => "User Error",512  => "User Warning",1024 => "User Notice");
   $dt=date("Y-m-d H:i:s (T)");
   $err='<table>' ;
   $err.='<tr><td><strong>URL:</strong></td><td><a href="http://'.$_SERVER['HTTP_HOST'].$SF_REQUEST_URI.'">http://'.$_SERVER['HTTP_HOST'].$SF_REQUEST_URI.'</a></td></tr>' ;
   $err.='<tr><td><strong>скрипт:</strong></td><td>'.$_SERVER['SCRIPT_FILENAME'].(($_SERVER['QUERY_STRING'])? '?'.$_SERVER['QUERY_STRING']:'').'</td></tr>' ;
   if ($filename) $err.='<tr><td><strong>файл:</strong></td><td>'.$filename.'":строка ("'.$linenum.'")</td></tr>' ;
   $err.='<tr><td><strong>время:</strong></td><td>'.$dt.'</td></tr>' ;
   if ($errno) $err.='<tr><td><strong>тип ошибки:</strong></td><td>'.$errortype[$errno].'</td></tr>' ;
   foreach($_SERVER as $name=>$value) $err.='<tr><td><strong>'.$name.'</strong></td><td>'.$value.'</td></tr>' ;
   $err.='</table>' ;
   return($err) ;
 }
?>
