App-Spoor
view release on metacpan or search on metacpan
lib/App/Spoor/AccessEntryParser.pm view on Meta::CPAN
use utf8;
=head1 NAME
App::Spoor::AccessEntryParser
=head1 VERSION
Version 0.02
=cut
our $VERSION = '0.02';
=head1 SYNOPSIS
This package contains the necessary functionality to parse CPanel access log entries.
=head1 SUBROUTINES/METHODS
=head2 parse
This subroutine accepts a single line from a CPanel access log (as a string) and returns a reference to a hash
representation of that entry.
The hash representation contains the following elements when the entry could be successfully parsed:
=over 2
=item * type: This is hardcoded to 'access'
=item * log_time: A DateTime instance representing the time of the log entry
=item * event: A description of the event that the entry refers to - can be one of forward_added_partial_ip, forward_removed, unrecognised.
=item * ip: The IP address listed in the entry
=item * credential: The user performing the request
=item * context: The context within which the operation is being performed can be either 'mailbox' or 'unrecognised'
=item * status: The status of the request can be one of 'success' or 'failed'
=back
If the entry could not be successfully parsed, it will contain the following items:
=over 2
=item * type: This is hardcoded to 'access'
=item * event: This is hardcoded to 'unrecognised'.
=back
=cut
sub parse {
use DateTime::Format::Strptime;
use URI::Escape qw( uri_unescape );
my $log_entry = shift;
my $level;
my $event;
my $status;
my $forward_recipient;
my %result;
my $date_parser = DateTime::Format::Strptime->new(pattern => '%m/%d/%Y:%H:%M:%S %z', on_error => 'croak');
if ($log_entry =~ /
\A
(?<ip>\S+)\s
-\s
(?<username>.+)\s
\[(?<timestamp>[^\]]+)\]\s
"(?<http_request>[^"]+)"\s
(?<response_code>\d{3})\s
/x) {
my $log_time = $date_parser->parse_datetime($+{timestamp})->epoch();
my $credential = uri_unescape($+{username});
my $ip = $+{ip};
my $http_request = $+{http_request};
my $response_code = $+{response_code};
if ($credential =~ /@/) {
$level = 'mailbox';
} else {
$level = 'unrecognised';
}
if ($response_code eq '200') {
$status = 'success';
} else {
$status = 'failed';
}
if ($credential =~ /@/ && $http_request =~ /\APOST.+doaddfwd.html/) {
$event = 'forward_added_partial_ip';
} elsif (
$credential =~ /@/ &&
$http_request =~ /\AGET.+dodelfwd.html\?.*emaildest=(?<forward_recipient>[^\s?]+)/
) {
$event = 'forward_removed';
$forward_recipient = uri_unescape($+{forward_recipient});
} else {
$event = 'unrecognised';
}
%result = (
type => 'access',
log_time => $log_time,
event => $event,
ip => $ip,
credential => $credential,
context => $level,
status => $status,
);
$result{forward_recipient} = $forward_recipient if($forward_recipient);
} else {
%result = (
type => 'access',
event => 'unrecognised',
);
}
\%result;
}
=head1 AUTHOR
Rory McKinley, C<< <rorymckinley at capefox.co> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-app-spoor at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=App-Spoor>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc App::Spoor::AccessEntryParser
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker (report bugs here)
L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=App-Spoor>
=item * AnnoCPAN: Annotated CPAN documentation
L<http://annocpan.org/dist/App-Spoor>
=item * CPAN Ratings
L<https://cpanratings.perl.org/d/App-Spoor>
=item * Search CPAN
L<https://metacpan.org/release/App-Spoor>
( run in 2.161 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )