#! /usr/bin/perl -w
# vim:syntax=perl

use strict;
use lib '/usr/local/share/perl5';
use Lire::Time;
use Lire::DlfSchema;
use Lire::Program qw( :msg :dlf );

my $schema      = Lire::DlfSchema::load_schema( "ftp" );
my $dlf_maker   =
  $schema->make_hashref2asciidlf_func(qw/time transfer_time remote_host
                                         file_size filename transfer_type
                                         special_action_flag direction
                                         access_mode username service_name
                                         auth_method auth_user_id
                                         completion_status /);
sub parseline {
    my $line = shift;

    my @fields = split(' ', $line);

    @fields >= 17 or
        die ("line '$line' has only " . @fields .
            " fields, should have at least 17\n");

    my %dlf = ();

    # easy stuff, i.e. fields that are simply copied and need no
    #                  conversion
    $dlf{transfer_time} = $fields[5];
    $dlf{remote_host}   = $fields[6];
    $dlf{file_size}     = $fields[7];
    $dlf{filename}      = $fields[8];
    $dlf{transfer_type} = $fields[9] eq 'b' ? 'binary' : 'ascii';
    if ( $fields[10] eq 'C' ) {
        $dlf{special_action_flag} = "compress";
    } elsif ( $fields[10] eq 'U' ) {
        $dlf{special_action_flag} = "uncompress";
    } elsif ( $fields[10] eq 'T' ) {
        $dlf{special_action_flag} = "tar";
    } elsif ( $fields[10] eq '_' ) {
        $dlf{special_action_flag} = undef;
    } else {
        die "unknown special_action value: $fields[10]\n";
    }
    $dlf{direction}     = $fields[11] eq 'i' ? 'upload' : 'download';
    if ( $fields[12] eq 'a' ) {
        $dlf{access_mode} = "anonymous";
    } elsif ( $fields[12] eq 'g' ) {
        $dlf{access_mode} = "guest";
    } elsif ( $fields[12] eq 'r' ) {
        $dlf{access_mode} = "authenticated";
    } else {
        die "unknown acces_mode value: $fields[12]\n";
    }
    $dlf{username}      = $fields[13];
    $dlf{service_name}  = $fields[14];
    $dlf{auth_method}   = $fields[15] ? 'ident' : 'none';
    $dlf{auth_user_id}  = $fields[16] ne '*' ? $fields[16] : undef;

    if ( defined $fields[17]) {
        $dlf{completion_status} =
          $fields[17] eq 'c' ? "complete" : "incomplete";
    }

    # $fields that need conversion. basically, only the time field
    $dlf{time} = date2cal($fields[4], $fields[1], $fields[2], $fields[3] );

    return $dlf_maker->( \%dlf );
}

init_dlf_converter( "ftp" );
my $lines       = 0;
my $dlflines    = 0;
my $errorlines  = 0;
while (<>) {
    chomp;
    $lines++;

    eval {
        my $dlf = parseline( $_ );
        print join( " ", @$dlf), "\n";
        $dlflines++;
    };
    if ($@) {
        lr_warn( $@ );
        lr_notice( qq{cannot convert line $. "$_" to ftp dlf, skipping} );
        $errorlines++;
    }
}
end_dlf_converter( $lines, $dlflines, $errorlines );

__END__

=pod

=head1 NAME

xferlog2dlf - convert FTP logs in xferlog format to DLF format

=head1 SYNOPSIS

B<xferlog2dlf>

=head1 DESCRIPTION

This script reads an FTP logfile in xferlog format. Most FTP servers
use this format, among these are ProFTPD, WU-FTPD.

=head1 EXAMPLES

To process a log as produced in the xferlog format:

 $ xferlog2dlf < ftp.log

xferlog2dlf will be rarely used on its own, but is more likely
called by lr_log2report:

 $ lr_log2report xferlog < /var/log/ftp.log

=head1 SEE ALSO

xferlog(5)

A list of FTP servers can be found at http://linuxmafia.com/pub/linux/security/ftp-daemons.

=head1 AUTHOR

Egon Willighagen <egonw@logreport.org>

=head1 VERSION

$Id: xferlog2dlf.in,v 1.11 2006/07/23 13:16:35 vanbaal Exp $

=head1 COPYRIGHT

Copyright (C) 2000-2001 Stichting LogReport Foundation LogReport@LogReport.org

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 this program (see COPYING); if not, check with
http://www.gnu.org/copyleft/gpl.html.

=cut

# Local Variables:
# mode: cperl
# End:
