'web_js')); $string = $_POST['message']; $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/\w+\//', '', $_POST['file'] ) : ''; if ( !empty( $_POST['line'] ) ) $line = $_POST['line']; else $line = NULL; $levels = array_flip(Logger::$codes); if ( !isset($levels[$_POST['level']]) ) Panic("Unexpected logger level '".$_POST['level']."'"); $level = $levels[$_POST['level']]; Logger::fetch()->logPrint( $level, $string, $file, $line ); } ajaxResponse(); break; } case 'query' : { if ( !canView('System') ) ajaxError('Insufficient permissions to view log entries'); $servers = Server::find_all(); $servers_by_Id = array(); # There is probably a better way to do this. foreach ( $servers as $server ) { $servers_by_Id[$server->Id()] = $server; } $minTime = isset($_REQUEST['minTime'])?$_REQUEST['minTime']:NULL; $maxTime = isset($_REQUEST['maxTime'])?$_REQUEST['maxTime']:NULL; $limit = 100; if ( isset($_REQUEST['limit']) ) { if ( ( !is_integer( $_REQUEST['limit'] ) and !ctype_digit($_REQUEST['limit']) ) ) { Error('Invalid value for limit ' . $_REQUEST['limit'] ); } else { $limit = $_REQUEST['limit']; } } $sortField = 'TimeKey'; if ( isset($_REQUEST['sortField']) ) { if ( ! in_array( $_REQUEST['sortField'], $filterFields ) and ( $_REQUEST['sortField'] != 'TimeKey' ) ) { Error("Invalid sort field " . $_REQUEST['sortField'] ); } else { $sortField = $_REQUEST['sortField']; } } $sortOrder = (isset($_REQUEST['sortOrder']) and $_REQUEST['sortOrder']) == 'asc' ? 'asc':'desc'; $filter = isset($_REQUEST['filter'])?$_REQUEST['filter']:array(); $total = dbFetchOne('SELECT count(*) AS Total FROM Logs', 'Total'); $sql = 'SELECT * FROM Logs'; $where = array(); $values = array(); if ( $minTime ) { $where[] = 'TimeKey > ?'; $values[] = $minTime; } elseif ( $maxTime ) { $where[] = 'TimeKey < ?'; $values[] = $maxTime; } foreach ( $filter as $field=>$value ) { if ( ! in_array($field, $filterFields) ) { Error("$field is not in valid filter fields"); continue; } if ( $field == 'Level' ){ $where[] = $field.' <= ?'; $values[] = $value; } else { $where[] = $field.' = ?'; $values[] = $value; } } $options = array(); if ( count($where) ) $sql.= ' WHERE '.join( ' AND ', $where ); $sql .= ' ORDER BY '.$sortField.' '.$sortOrder.' LIMIT '.$limit; $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['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 ) { if ( ! isset( $options[$field] ) ) $options[$field] = array(); $value = $log[$field]; if ( $field == 'Level' ) { if ( $value <= Logger::INFO ) $options[$field][$value] = Logger::$codes[$value]; else $options[$field][$value] = 'DB'.$value; } else if ( $field == 'ServerId' ) { $options['ServerId'][$value] = ( $value and isset($servers_by_Id[$value]) ) ? $servers_by_Id[$value]->Name() : ''; } else if ( isset($log[$field]) ) { $options[$field][$log[$field]] = $log[$field]; } } $logs[] = $log; } $available = count($logs); 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' : { 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 ) { $tempTime = $minTime; $minTime = $maxTime; $maxTime = $tempTime; } //$limit = isset($_POST['limit'])?$_POST['limit']:1000; $filter = isset($_POST['filter'])?$_POST['filter']:array(); $sortField = 'TimeKey'; if ( isset($_POST['sortField']) ) { if ( ! in_array( $_POST['sortField'], $filterFields ) and ( $_POST['sortField'] != 'TimeKey' ) ) { Error("Invalid sort field " . $_POST['sortField'] ); } else { $sortField = $_POST['sortField']; } } $sortOrder = (isset($_POST['sortOrder']) and $_POST['sortOrder']) == 'asc' ? 'asc':'desc'; $servers = Server::find_all(); $servers_by_Id = array(); # There is probably a better way to do this. foreach ( $servers as $server ) { $servers_by_Id[$server->Id()] = $server; } $sql = 'SELECT * FROM Logs'; $where = array(); $values = array(); if ( $minTime ) { preg_match('/(.+)(\.\d+)/', $minTime, $matches); $minTime = strtotime($matches[1]).$matches[2]; $where[] = 'TimeKey >= ?'; $values[] = $minTime; } if ( $maxTime ) { preg_match('/(.+)(\.\d+)/', $maxTime, $matches); $maxTime = strtotime($matches[1]).$matches[2]; $where[] = 'TimeKey <= ?'; $values[] = $maxTime; } foreach ( $filter as $field=>$value ) { if ( $value != '' ) { if ( $field == 'Level' ) { $where[] = $field.' <= ?'; $values[] = $value; } else { $where[] = $field.' = ?'; $values[] = $value; } } } if ( count($where) ) $sql.= ' WHERE '.join( ' AND ', $where ); $sql .= ' ORDER BY '.$sortField.' '.$sortOrder; //$sql .= " limit ".dbEscape($limit); $format = isset($_POST['format'])?$_POST['format']:'text'; switch( $format ) { case 'text' : $exportExt = 'txt'; break; case 'tsv' : $exportExt = 'tsv'; break; case 'html' : $exportExt = 'html'; break; case 'xml' : $exportExt = 'xml'; break; default : Fatal("Unrecognised log export format '$format'"); } $exportKey = substr(md5(rand()),0,8); $exportFile = "zm-log.$exportExt"; $exportPath = ZM_PATH_SWAP."/zm-log-$exportKey.$exportExt"; if ( !($exportFP = fopen( $exportPath, "w" )) ) 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['Server'] = ( $log['ServerId'] and isset($servers_by_Id[$log['ServerId']]) ) ? $servers_by_Id[$log['ServerId']]->Name() : ''; $logs[] = $log; } 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'] ); else 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", translate('DateTime'), translate('Component'), translate('Server'), translate('Pid'), translate('Level'), translate('Message'), translate('File'), translate('Line') )."\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'] ); } break; } case 'html' : { fwrite( $exportFP, '
'.htmlspecialchars(preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG )).'
'.count($logs).' '.translate('Logs').'
'.translate('DateTime').' | '.translate('Component').' | '.translate('Server').' | '.translate('Pid').' | '.translate('Level').' | '.translate('Message').' | '.translate('File').' | '.translate('Line').' |
---|---|---|---|---|---|---|---|
%s | %s | %s | %d | %s | %s | %s | %s |