#/*
# *  Copyright 2007 hkrn <hikarin@users.sourceforge.jp>
# *
# *  Licensed under the Apache License, Version 2.0 (the "License");
# *  you may not use this file except in compliance with the License.
# *  You may obtain a copy of the License at
# *
# *      http://www.apache.org/licenses/LICENSE-2.0
# *
# *  Unless required by applicable law or agreed to in writing, software
# *  distributed under the License is distributed on an "AS IS" BASIS,
# *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# *  See the License for the specific language governing permissions and
# *  limitations under the License.
# */
#
# $Id: log.pm 1865 2009-09-13 13:38:42Z hikarin $
#

package Zeromin2::App::log;

use strict;

sub load_error {
    my ($zApp) = @_;
    $zApp->privilege('can_view_error_log')
        or return $zApp->return_value( 1, [] );
    my ( $content, $page );

    my $iRequest = $zApp->request();
    my $type     = $iRequest->param('type');
    my $date     = $iRequest->param('date');
    my ( $day, $month, $year ) = _parse_date( $iRequest, $date );

    require Zeromin::Log::Error;
    my $iBBS      = $zApp->bbs();
    my $zLogErr   = Zeromin::Log::Error->new( $iBBS || $zApp->kernel() );
    my $by        = $iRequest->param('by');
    my $key       = $iRequest->param('key');
    my $page_name = 'log_error';
    $zLogErr->load();

    my $template_tag = {};
    if ( $by eq 'all' ) {

        # Img0ch::BBS => bbs_dir | Img0ch::Kernel => undef
        ( $content, $page )
            = $zLogErr->all_in_with_page( undef, $key,
            $zApp->page_param($page_name) );
        %$template_tag = ( IsAll => 1 );
    }
    elsif ( $by eq 'month' ) {

        # Img0ch::BBS => bbs_dir | Img0ch::Kernel => undef
        ( $content, $page )
            = $zLogErr->retrive_by_month_in_with_page( $year, $month, undef,
            $key, $zApp->page_param($page_name) );
        _get_template_tag_by_month( $template_tag, $year, $month, $day );
    }
    else {

        # Img0ch::BBS => bbs_dir | Img0ch::Kernel => undef
        ( $content, $page )
            = $zLogErr->retrive_by_day_in_with_page( $year, $month, $day,
            undef, $key, $zApp->page_param($page_name) );
        _get_template_tag_by_day( $template_tag, $year, $month, $day );
    }

    if ($iBBS) {
        my $iKernel  = $iBBS->get_kernel();
        my $iSubject = $iBBS->get_subject_instance();
        my $encoding = $iKernel->get_encoding(1);
        for my $log (@$content) {
            my $subject = $iSubject->get( $log->{key} )->[0];
            $log->{subject}
                = $iKernel->get_encoded_str( $subject, 'utf8', $encoding );
        }
    }

    _format_date( $content, 'date' );
    $zApp->add_template_param(
        {   %$template_tag,
            By   => $by,
            Date => $date,
            Type => 'error',
        }
    );

    return $zApp->return_value( 0, $content, $page );
}

sub download_error {
    my ($zApp) = @_;
    $zApp->prevent_saving_session();
    $zApp->privilege('can_view_error_log')
        or return $zApp->return_value( 1, [] );

    $zApp->content_type('text/x-csv');
    $zApp->request()
        ->set_header( 'content-disposition',
        'attachment; filename="' . _filename('error') . '"' );
    return load_error($zApp);
}

sub load_user {
    my ($zApp) = @_;
    $zApp->privilege('can_view_zeromin_log')
        or return $zApp->return_value( 1, [] );
    my ( $content, $page );

    my $iRequest = $zApp->request();
    my $type     = $iRequest->param('type');
    my $date     = $iRequest->param('date');
    my ( $day, $month, $year ) = _parse_date( $iRequest, $date );

    require Zeromin::Log::Action;
    my $zUser     = $zApp->user();
    my $zLogAct   = Zeromin::Log::Action->new( $zApp->kernel() );
    my $by        = $iRequest->param('by');
    my $page_name = 'log_user';

    my $template_tag = {};
    if ( $by eq 'all' ) {
        ( $content, $page )
            = $zLogAct->all_with_page( $zUser, '',
            $zApp->page_param($page_name) );
        %$template_tag = ( IsAll => 1 );
    }
    elsif ( $by eq 'month' ) {
        ( $content, $page )
            = $zLogAct->retrive_by_month_with_page( $year, $month, $zUser,
            $zApp->page_param($page_name) );
        _get_template_tag_by_month( $template_tag, $year, $month, $day );
    }
    else {
        ( $content, $page )
            = $zLogAct->retrive_by_day_with_page( $year, $month, $day, $zUser,
            $zApp->page_param($page_name) );
        _get_template_tag_by_day( $template_tag, $year, $month, $day );
    }

    _format_date( $content, 'date' );
    $zApp->add_template_param(
        {   %$template_tag,
            By   => $by,
            Date => $date,
            Type => 'user',
        }
    );
    return $zApp->return_value( 0, $content, $page );
}

sub download_user {
    my ($zApp) = @_;
    $zApp->prevent_saving_session();
    $zApp->privilege('can_view_zeromin_log')
        or return $zApp->return_value( 1, [] );

    $zApp->content_type('text/x-csv');
    $zApp->request()
        ->set_header( 'content-disposition',
        'attachment; filename="' . _filename('user') . '"' );
    return load_user($zApp);
}

sub load_host {
    my ($zApp) = @_;
    $zApp->privilege( 'can_view_thread_log', 1 )
        or return $zApp->return_value( 1, [] );
    my ( $content, $page );

    require Zeromin::Log;
    my $iBBS     = $zApp->bbs();
    my $iKernel  = $zApp->kernel();
    my $iSubject = $iBBS->get_subject_instance();
    my $zLog     = Zeromin::Log->new($iBBS);
    my $encoding = $iKernel->get_encoding(1);
    $zLog->load();

    my ( $content, $page )
        = $zLog->all_with_page( $zApp->page_param('log_host') );
    _format_date( $content, 'date' );
    for my $log (@$content) {
        my $subject = $iSubject->get( $log->{key} )->[0];
        $log->{subject}
            = $iKernel->get_encoded_str( $subject, 'utf8', $encoding );
    }
    $zApp->add_template_param( { Type => 'host' } );

    return $zApp->return_value( 0, $content, $page );
}

sub download_host {
    my ($zApp) = @_;
    $zApp->prevent_saving_session();
    $zApp->privilege( 'can_view_thread_log', 1 )
        or return $zApp->return_value( 1, [] );

    $zApp->content_type('text/x-csv');
    $zApp->request()
        ->set_header( 'content-disposition',
        'attachment; filename="' . _filename('user') . '"' );

    return load_host($zApp);
}

sub load_thread {
    my ($zApp) = @_;
    $zApp->privilege( 'can_view_thread_log', 1 )
        or return $zApp->return_value( 1, [] );

    require Zeromin::Log::Thread;
    my $zLogThr = Zeromin::Log::Thread->new( $zApp->bbs() );
    $zLogThr->load();

    my ( $content, $page )
        = $zLogThr->all_with_page( $zApp->page_param('log_thread') );
    _format_date( $content, 'atime' );
    $zApp->add_template_param( { Type => 'thread' } );

    return $zApp->return_value( 0, $content, $page );
}

sub download_thread {
    my ($zApp) = @_;
    $zApp->prevent_saving_session();
    $zApp->privilege('can_view_thread_log')
        or return $zApp->return_value( 1, [] );

    $zApp->content_type('text/csv');
    $zApp->request()
        ->set_header( 'content-disposition',
        'attachment; filename="' . _filename('thread') . '"' );
    return load_thread($zApp);
}

sub lookup {
    my ($zApp) = @_;
           $zApp->privilege('can_view_thread_log')
        or $zApp->privilege('can_view_error_log')
        or $zApp->privilege('can_enter_log_section')
        or return $zApp->return_value(1);

    require Img0ch::Plugin::Module::DNSBL;
    require Img0ch::Plugin::Module::RACC;

    my $ip = $zApp->request()->param('ip');
    if ( $ip !~ /\A(\d+)\.(\d+)\.(\d+)\.(\d+)\z/xms ) {
        $zApp->add_template_param(
            {   Country  => '**',
                Listed   => [],
                Resolved => '(null)'
            }
        );
        return $zApp->return_value(2);
    }
    my @ipaddr = ( $1, $2, $3, $4 );

    my $cc = eval {
        return Img0ch::Plugin::Module::RACC->get( $ip,
            $zApp->kernel()->get_config() );
    } || '--';

    my $ret = {};
    my $host = gethostbyaddr( pack( 'C*', @ipaddr ), 2 ) || $ip;
    for my $dnsbl ( 'bbx', 'bbq', 'livedoor' ) {
        $ret->{ Img0ch::Plugin::Module::DNSBL->get_hostname($dnsbl) }
            = Img0ch::Plugin::Module::DNSBL->is_in_dnsbl( $dnsbl, undef,
            $ip );
    }

    my $stack = [];
    map { push @$stack, { $_ => $ret->{$_} } } keys %$ret;

    $zApp->add_template_param(
        {   Country  => $cc,
            Listed   => $stack,
            Resolved => $host
        }
    );
    return $zApp->return_value( 0,
        { resolved => $host, country => $cc, listed => $ret } );
}

sub _filename {
    my ($prefix) = @_;
    my ( undef, undef, undef, $current_day, $current_month, $current_year )
        = localtime( time() );
    $current_year  += 1900;
    $current_month += 1;
    return sprintf '%04d-%02d-%02d-%s.csv', $current_year, $current_month,
        $current_day, $prefix;
}

sub _format_date {
    my ( $content, $key ) = @_;
    require Zeromin2::Util;
    map { $_->{$key} = Zeromin2::Util::format_date( $_->{$key} ) } @$content;
    return;
}

sub _parse_date {
    my ( $iRequest, $date ) = @_;
    my ( $current_day, $current_month, $current_year, $day, $month, $year );
    if ( $date =~ m{\A(\d{4})[/\-](\d{2})[/\-](\d{2})\z}xms ) {
        ( $year, $month, $day ) = (
            Img0ch::Kernel::intval($1),
            Img0ch::Kernel::intval($2),
            Img0ch::Kernel::intval($3)
        );
    }
    else {
        my ( undef, undef, undef, $current_day, $current_month,
            $current_year )
            = localtime( time() );
        $current_year  += 1900;
        $current_month += 1;
        $year  = $iRequest->param_int('year')  || $current_year;
        $month = $iRequest->param_int('month') || $current_month;
        $day   = $iRequest->param_int('day')   || $current_day;
    }
    return ( $day, $month, $year );
}

sub _get_template_tag_by_day {
    my ( $template_tag, $year, $month, $day ) = @_;
    require Zeromin2::Util;
    %$template_tag = (
        IsDay   => 1,
        NextDay => sprintf( '%04d-%02d-%02d',
            Zeromin2::Util::get_next_ymd_by_day( $year, $month, $day ) ),
        PrevDay => sprintf( '%04d-%02d-%02d',
            Zeromin2::Util::get_previous_ymd_by_day( $year, $month, $day ) ),
    );
    return;
}

sub _get_template_tag_by_month {
    my ( $template_tag, $year, $month, $day ) = @_;
    require Zeromin2::Util;
    %$template_tag = (
        IsMonth   => 1,
        NextMonth => sprintf( '%04d-%02d-%02d',
            Zeromin2::Util::get_next_ymd_by_month( $year, $month, $day ) ),
        PrevMonth => sprintf( '%04d-%02d-%02d',
            Zeromin2::Util::get_previous_ymd_by_month( $year, $month, $day )
        ),
    );
    return;
}

1;
__END__
