# POPFILE LOADABLE MODULE
package POPFile::Logger;
use POPFile::Module;
@ISA = ("POPFile::Module");
#----------------------------------------------------------------------------
#
# This module handles POPFile's logger. It is used to save debugging
# information to disk or to send it to the screen.
#
# Copyright (c) 2001-2006 John Graham-Cumming
#
# This file is part of POPFile
#
# POPFile is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# POPFile is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with POPFile; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#----------------------------------------------------------------------------
use strict;
use warnings;
use locale;
# Constant used by the log rotation code
my $seconds_per_day = 60 * 60 * 24;
#----------------------------------------------------------------------------
# new
#
# Class new() function
#----------------------------------------------------------------------------
sub new
{
my $proto = shift;
my $class = ref($proto) || $proto;
my $self = POPFile::Module->new();
# The name of the debug file
$self->{debug_filename__} = '';
# The last ten lines sent to the logger
$self->{last_ten__} = ();
$self->{initialize_called__} = 0;
bless($self, $class);
$self->name( 'logger' );
return $self;
}
#----------------------------------------------------------------------------
#
# initialize
#
# Called to initialize the interface
#
# ---------------------------------------------------------------------------
sub initialize
{
my ( $self ) = @_;
$self->{initialize_called__} = 1;
# Start with debugging to file
$self->global_config_( 'debug', 1 );
# The default location for log files
$self->config_( 'logdir', './' );
# The output format for log files, can be default, tabbed or csv
$self->config_( 'format', 'default' );
# The log level. There are three levels of log:
#
# 0 Critical log messages
# 1 Verbose logging
# 2 Maximum verbosity
$self->config_( 'level', 0 );
$self->{last_tickd__} = time;
$self->mq_register_( 'TICKD', $self );
return 1;
}
# ---------------------------------------------------------------------------
#
# deliver
#
# Called by the message queue to deliver a message
#
# There is no return value from this method
#
# ---------------------------------------------------------------------------
sub deliver
{
my ( $self, $type, @message ) = @_;
# If a day has passed then clean up log files
if ( $type eq 'TICKD' ) {
$self->remove_debug_files();
}
}
#----------------------------------------------------------------------------
#
# start
#
# Called to start the logger running
#
#----------------------------------------------------------------------------
sub start
{
my ( $self ) = @_;
$self->calculate_today__();
return 1;
}
# ---------------------------------------------------------------------------
#
# service
#
# ---------------------------------------------------------------------------
sub service
{
my ( $self ) = @_;
$self->calculate_today__();
# We send out a TICKD message every hour so that other modules
# can do clean up tasks that need to be done regularly but not
# often
if ( time > ( $self->{last_tickd__} + 3600 ) ) {
$self->mq_post_( 'TICKD' );
$self->{last_tickd__} = time;
}
return 1;
}
# ---------------------------------------------------------------------------
#
# calculate_today
#
# Set the global $self->{today} variable to the current day in seconds
#
# ---------------------------------------------------------------------------
sub calculate_today__
{
my ( $self ) = @_;
# Create the name of the debug file for the debug() function
$self->{today__} = int( time / $seconds_per_day ) * $seconds_per_day;
# Note that 0 parameter than allows the logdir to be outside the user
# sandbox
$self->{debug_filename__} = $self->get_user_path_(
$self->config_( 'logdir' ) . "popfile$self->{today__}.log", 0 );
}
# ---------------------------------------------------------------------------
#
# remove_debug_files
#
# Removes popfile log files that are older than 3 days
#
# ---------------------------------------------------------------------------
sub remove_debug_files
{
my ( $self ) = @_;
my @debug_files = glob( $self->get_user_path_(
$self->config_( 'logdir' ) . 'popfile*.log', 0 ) );
foreach my $debug_file (@debug_files) {
# Extract the epoch information from the popfile log file name
if ( $debug_file =~ /popfile([0-9]+)\.log/ ) {
# If older than now - 3 days then delete
unlink($debug_file) if ( $1 < (time - 3 * $seconds_per_day) );
}
}
}
# ----------------------------------------------------------------------------
#
# debug
#
# $level The level of this message
# $message A string containing a debug message that may or may not be
# printed
#
# Prints the passed string if the global $debug is true
#
# ----------------------------------------------------------------------------
sub debug
{
my ( $self, $level, $message ) = @_;
if ( $self->{initialize_called__} == 0 ) {
return;
}
if ( $level > $self->config_( 'level' ) ) {
return;
}
if ( $self->{debug_filename__} eq '' ) {
return;
}
if ( $self->global_config_( 'debug' ) > 0 ) {
# Check to see if we are handling the USER/PASS command and if
# we are then obscure the account information
if ( $message =~ /((--)?)(USER|PASS)\s+\S*(\1)/i ) {
$message = "$`$1$3 XXXXXX$4";
}
$message =~ s/([\x00-\x1f])/sprintf("[%2.2x]", ord($1))/eg;
my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
localtime;
$year += 1900;
$mon += 1;
$min = "0$min" if ( $min < 10 );
$hour = "0$hour" if ( $hour < 10 );
$sec = "0$sec" if ( $sec < 10 );
my $delim = ' ';
$delim = "\t" if ( $self->config_( 'format' ) eq 'tabbed' );
$delim = ',' if ( $self->config_( 'format' ) eq 'csv' );
my $msg =
"$year/$mon/$mday$delim$hour:$min:$sec$delim$$:$delim$message\n";
if ( $self->global_config_( 'debug' ) & 1 ) {
if ( open DEBUG, ">>$self->{debug_filename__}" ) {
print DEBUG $msg;
close DEBUG;
}
}
print $msg if ( $self->global_config_( 'debug' ) & 2 );
# Add the line to the in memory collection of the last ten
# logger entries and then remove the first one if we now have
# more than 10
push @{$self->{last_ten__}}, ($msg);
if ( $#{$self->{last_ten__}} > 9 ) {
shift @{$self->{last_ten__}};
}
}
}
# GETTERS/SETTERS
sub debug_filename
{
my ( $self ) = @_;
return $self->{debug_filename__};
}
sub last_ten
{
my ( $self ) = @_;
if ( $#{$self->{last_ten__}} >= 0 ) {
return @{$self->{last_ten__}};
} else {
my @temp = ( 'log empty' );
return @temp;
}
}
1;
syntax highlighted by Code2HTML, v. 0.9.1