cleanup. Don't output errors that break json response

This commit is contained in:
Isaac Connor 2020-04-10 11:10:57 -04:00
parent 3ac6dc267b
commit 59f9f37fff
1 changed files with 70 additions and 72 deletions

View File

@ -1,14 +1,15 @@
<?php
ini_set('display_errors', '0');
# Moved up here because it is used in several spots.
# These are the valid columns that you can filter on.
$filterFields = array( 'Component', 'ServerId', 'Pid', 'Level', 'File', 'Line' );
$filterFields = array('Component', 'ServerId', 'Pid', 'Level', 'File', 'Line');
function buildLogQuery($action) {
global $filterFields;
$minTime = isset($_REQUEST['minTime'])?$_REQUEST['minTime']:NULL;
$maxTime = isset($_REQUEST['maxTime'])?$_REQUEST['maxTime']:NULL;
$minTime = isset($_REQUEST['minTime']) ? $_REQUEST['minTime'] : NULL;
$maxTime = isset($_REQUEST['maxTime']) ? $_REQUEST['maxTime'] : NULL;
$limit = 100;
if ( isset($_REQUEST['limit']) ) {
@ -42,10 +43,10 @@ function buildLogQuery($action) {
foreach ( $filter as $field=>$value ) {
if ( !in_array($field, $filterFields) ) {
ZM\Error("'$field' is not in valid filter fields " . print_r($filterField,true));
ZM\Error("'$field' is not in valid filter fields " . print_r($filterField, true));
continue;
}
if ( $field == 'Level' ){
if ( $field == 'Level' ) {
$where[] = $field.' <= ?';
$values[] = $value;
} else {
@ -69,8 +70,8 @@ switch ( $_REQUEST['task'] ) {
$string = $_POST['message'];
$file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : '';
if ( !empty( $_POST['line'] ) ) {
$file = !empty($_POST['file']) ? preg_replace('/\w+:\/\/[\w.:]+\//', '', $_POST['file']) : '';
if ( !empty($_POST['line']) ) {
$line = validInt($_POST['line']);
} else {
$line = NULL;
@ -82,6 +83,8 @@ switch ( $_REQUEST['task'] ) {
}
$level = $levels[$_POST['level']];
ZM\Logger::fetch()->logPrint($level, $string, $file, $line);
} else {
ZM\Error('Invalid log create: '.print_r($_POST, true));
}
ajaxResponse();
break;
@ -93,12 +96,7 @@ switch ( $_REQUEST['task'] ) {
$query = buildLogQuery('DELETE');
$result = dbQuery($query['sql'], $query['values']);
ajaxResponse( array(
'result'=>'Ok',
'deleted'=>$result->rowCount(),
) );
ajaxResponse(array('result'=>'Ok', 'deleted'=>$result->rowCount()));
}
case 'query' :
{
@ -107,10 +105,12 @@ switch ( $_REQUEST['task'] ) {
$total = dbFetchOne('SELECT count(*) AS Total FROM Logs', 'Total');
$query = buildLogQuery('SELECT *');
$servers = ZM\Server::find();
global $Servers;
if ( !$Servers )
$Servers = ZM\Server::find();
$servers_by_Id = array();
# There is probably a better way to do this.
foreach ( $servers as $server ) {
foreach ( $Servers as $server ) {
$servers_by_Id[$server->Id()] = $server;
}
@ -120,11 +120,9 @@ switch ( $_REQUEST['task'] ) {
foreach ( dbFetchAll($query['sql'], NULL, $query['values']) as $log ) {
$log['DateTime'] = strftime('%Y-%m-%d %H:%M:%S', intval($log['TimeKey']));
#Warning("TimeKey: " . $log['TimeKey'] . 'Intval:'.intval($log['TimeKey']).' DateTime:'.$log['DateTime']);
#$log['DateTime'] = preg_replace('/^\d+/', strftime('%Y-%m-%d %H:%M:%S', intval($log['TimeKey'])), $log['TimeKey']);
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
$log['Message'] = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $log['Message']);
foreach( $filterFields as $field ) {
foreach ( $filterFields as $field ) {
if ( !isset($options[$field]) )
$options[$field] = array();
$value = $log[$field];
@ -141,21 +139,21 @@ switch ( $_REQUEST['task'] ) {
}
}
$logs[] = $log;
}
} # end foreach log db row
foreach ( $options as $field => $values ) {
asort($options[$field]);
}
$available = count($logs);
ajaxResponse( array(
'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG)?strftime(DATE_FMT_CONSOLE_LONG):date(DATE_FMT_CONSOLE_LONG),
ajaxResponse(array(
'updated' => preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG),
'total' => $total,
'available' => isset($available) ? $available : $total,
'logs' => $logs,
'state' => logState(),
'options' => $options,
) );
));
break;
}
case 'export' :
@ -163,9 +161,9 @@ switch ( $_REQUEST['task'] ) {
if ( !canView('System') )
ajaxError('Insufficient permissions to export logs');
$minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL;
$maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL;
if ( !is_null($minTime) && !is_null($maxTime) && $minTime > $maxTime ) {
$minTime = isset($_POST['minTime']) ? $_POST['minTime'] : NULL;
$maxTime = isset($_POST['maxTime']) ? $_POST['maxTime'] : NULL;
if ( !is_null($minTime) && !is_null($maxTime) && ($minTime > $maxTime) ) {
$tempTime = $minTime;
$minTime = $maxTime;
$maxTime = $tempTime;
@ -174,15 +172,17 @@ switch ( $_REQUEST['task'] ) {
$filter = isset($_POST['filter'])?$_POST['filter']:array();
$sortField = 'TimeKey';
if ( isset($_POST['sortField']) ) {
if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) {
ZM\Error("Invalid sort field " . $_POST['sortField'] );
if ( !in_array($_POST['sortField'], $filterFields) and ($_POST['sortField'] != 'TimeKey') ) {
ZM\Error('Invalid sort field '.$_POST['sortField']);
} else {
$sortField = $_POST['sortField'];
}
}
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc';
$sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc' : 'desc';
$servers = ZM\Server::find();
global $Servers;
if ( !$Servers )
$Servers = ZM\Server::find();
$servers_by_Id = array();
# There is probably a better way to do this.
foreach ( $servers as $server ) {
@ -193,11 +193,9 @@ switch ( $_REQUEST['task'] ) {
$where = array();
$values = array();
if ( $minTime ) {
ZM\Logger::Debug("MinTime: $minTime");
if ( preg_match('/(.+)(\.\d+)/', $minTime, $matches) ) {
# This handles sub second precision
$minTime = strtotime($matches[1]).$matches[2];
ZM\Logger::Debug("MinTime: $minTime");
} else {
$minTime = strtotime($minTime);
}
@ -225,11 +223,11 @@ switch ( $_REQUEST['task'] ) {
}
}
if ( count($where) )
$sql.= ' WHERE '.join( ' AND ', $where );
$sql.= ' WHERE '.join(' AND ', $where);
$sql .= ' ORDER BY '.$sortField.' '.$sortOrder;
//$sql .= " limit ".dbEscape($limit);
$format = isset($_POST['format'])?$_POST['format']:'text';
switch( $format ) {
$format = isset($_POST['format']) ? $_POST['format'] : 'text';
switch ( $format ) {
case 'text' :
$exportExt = 'txt';
break;
@ -245,43 +243,40 @@ switch ( $_REQUEST['task'] ) {
default :
ZM\Fatal("Unrecognised log export format '$format'");
}
$exportKey = substr(md5(rand()),0,8);
$exportFile = "zm-log.$exportExt";
if ( ! file_exists(ZM_DIR_EXPORTS) ) {
ZM\Logger::Debug('Creating ' . ZM_DIR_EXPORTS);
if ( ! mkdir(ZM_DIR_EXPORTS) ) {
ZM\Fatal("Can't create exports dir at '".ZM_DIR_EXPORTS."'");
}
$exportKey = substr(md5(rand()), 0, 8);
$exportFile = 'zm-log.'.$exportExt;
if ( ! ( mkdir(ZM_DIR_EXPORTS) || file_exists(ZM_DIR_EXPORTS) ) ) {
ZM\Fatal('Can\'t create exports dir at \''.ZM_DIR_EXPORTS.'\'');
}
$exportPath = ZM_DIR_EXPORTS."/zm-log-$exportKey.$exportExt";
$exportPath = ZM_DIR_EXPORTS.'/zm-log-'.$exportKey.$exportExt;
ZM\Logger::Debug("Exporting to $exportPath");
if ( !($exportFP = fopen($exportPath, 'w')) )
ZM\Fatal("Unable to open log export file $exportPath");
$logs = array();
foreach ( dbFetchAll($sql, NULL, $values) as $log ) {
$log['DateTime'] = preg_replace('/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey']);
$log['DateTime'] = preg_replace('/^\d+/', strftime('%Y-%m-%d %H:%M:%S', intval($log['TimeKey'])), $log['TimeKey']);
$log['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : '';
$logs[] = $log;
}
ZM\Logger::Debug(count($logs)." lines being exported by $sql " . implode(',',$values));
ZM\Logger::Debug(count($logs).' lines being exported by '.$sql.implode(',', $values));
switch( $format ) {
case 'text' :
{
foreach ( $logs as $log ) {
if ( $log['Line'] )
fprintf( $exportFP, "%s %s[%d].%s-%s/%d [%s]\n",
$log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Line'], $log['Message'] );
fprintf($exportFP, "%s %s[%d].%s-%s/%d [%s]\n",
$log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Line'], $log['Message']);
else
fprintf( $exportFP, "%s %s[%d].%s-%s [%s]\n",
$log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Message'] );
fprintf($exportFP, "%s %s[%d].%s-%s [%s]\n",
$log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Message']);
}
break;
}
case 'tsv' :
{
# This line doesn't need fprintf, it could use fwrite
fprintf( $exportFP, join( "\t",
fprintf($exportFP, join("\t",
translate('DateTime'),
translate('Component'),
translate('Server'),
@ -290,17 +285,17 @@ switch ( $_REQUEST['task'] ) {
translate('Message'),
translate('File'),
translate('Line')
)."\n" );
)."\n");
foreach ( $logs as $log ) {
fprintf( $exportFP, "%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] );
fprintf($exportFP, "%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\n",
$log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line']);
}
break;
}
case 'html' :
{
fwrite( $exportFP,
'
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
fwrite($exportFP,
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>'.translate('ZoneMinderLog').'</title>
@ -339,34 +334,36 @@ switch ( $_REQUEST['task'] ) {
</head>
<body>
<h3>'.translate('ZoneMinderLog').'</h3>
<p>'.htmlspecialchars(preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG )).'</p>
<p>'.htmlspecialchars(preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG)).'</p>
<p>'.count($logs).' '.translate('Logs').'</p>
<table>
<tbody>
<tr><th>'.translate('DateTime').'</th><th>'.translate('Component').'</th><th>'.translate('Server').'</th><th>'.translate('Pid').'</th><th>'.translate('Level').'</th><th>'.translate('Message').'</th><th>'.translate('File').'</th><th>'.translate('Line').'</th></tr>
' );
');
foreach ( $logs as $log ) {
$classLevel = $log['Level'];
if ( $classLevel < ZM\Logger::FATAL )
if ( $classLevel < ZM\Logger::FATAL ) {
$classLevel = ZM\Logger::FATAL;
elseif ( $classLevel > ZM\Logger::DEBUG )
} else if ( $classLevel > ZM\Logger::DEBUG ) {
$classLevel = ZM\Logger::DEBUG;
}
$logClass = 'log-'.strtolower(ZM\Logger::$codes[$classLevel]);
fprintf( $exportFP, " <tr class=\"%s\"><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n", $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] );
fprintf($exportFP, ' <tr class="%s"><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>
', $logClass, $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line']);
}
fwrite( $exportFP,
fwrite($exportFP,
' </tbody>
</table>
</body>
</html>' );
</html>');
break;
}
case 'xml' :
{
fwrite( $exportFP,
fwrite($exportFP,
'<?xml version="1.0" encoding="utf-8"?>
<logexport title="'.translate('ZoneMinderLog').'" date="'.htmlspecialchars(preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG )).'">
<selector>'.$_POST['selector'].'</selector>' );
<logexport title="'.translate('ZoneMinderLog').'" date="'.htmlspecialchars(preg_match('/%/', DATE_FMT_CONSOLE_LONG) ? strftime(DATE_FMT_CONSOLE_LONG) : date(DATE_FMT_CONSOLE_LONG)).'">
<selector>'.$_POST['selector'].'</selector>');
foreach ( $filter as $field=>$value )
if ( $value != '' )
fwrite( $exportFP,
@ -381,7 +378,7 @@ switch ( $_REQUEST['task'] ) {
' );
foreach ( $logs as $log ) {
fprintf( $exportFP,
" <log>
' <log>
<datetime>%s</datetime>
<component>%s</component>
<server>%s</server>
@ -390,7 +387,8 @@ switch ( $_REQUEST['task'] ) {
<message><![CDATA[%s]]></message>
<file>%s</file>
<line>%d</line>
</log>\n", $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] );
</log>
', $log['DateTime'], $log['Component'], $log['Server'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] );
}
fwrite( $exportFP,
' </logs>
@ -419,7 +417,7 @@ switch ( $_REQUEST['task'] ) {
ZM\Fatal('No log export format given');
$format = $_REQUEST['format'];
switch( $format ) {
switch ( $format ) {
case 'text' :
$exportExt = 'txt';
break;
@ -436,15 +434,15 @@ switch ( $_REQUEST['task'] ) {
ZM\Fatal("Unrecognised log export format '$format'");
}
$exportFile = "zm-log.$exportExt";
$exportPath = ZM_DIR_EXPORTS."/zm-log-$exportKey.$exportExt";
$exportFile = 'zm-log.'.$exportExt;
$exportPath = ZM_DIR_EXPORTS.'/zm-log-'.$exportKey.$exportExt;
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false ); // required by certain browsers
header('Cache-Control: private', false); // required by certain browsers
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="'.$exportFile.'"' );
header('Content-Disposition: attachment; filename="'.$exportFile.'"');
header('Content-Transfer-Encoding: binary');
header('Content-Type: application/force-download');
header('Content-Length: '.filesize($exportPath));
@ -452,6 +450,6 @@ switch ( $_REQUEST['task'] ) {
exit(0);
break;
}
}
} // end switch ( $_REQUEST['task'] )
ajaxError('Unrecognised action or insufficient permissions');
?>