#/*
# *  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: filter.pm 363 2007-03-16 15:11:10Z hikarin $
#

package Zeromin::App::filter;

use strict;

sub load {
    my ($zApp) = @_;
    my $zUser    = $zApp->user() || return { code => 1 };
    my $iRequest = $zApp->request();
    my $args     = ( $zApp->bbs() || $zApp->kernel() );
    my $ret;

    my $type = $iRequest->param('type');
    if ( $type eq 'ip' ) {
        $zUser->can_enter_control_section() or return { code => 1 };
        require Zeromin::Filter::IP;
        my $zFIP = Zeromin::Filter::IP->new($args);
        $zFIP->load();
        $ret = $zFIP->all_in();
    }
    elsif ( $type eq 'host' ) {
        $zUser->can_enter_control_section() or return { code => 1 };
        require Zeromin::Filter::RemoteHost;
        my $zFRH = Zeromin::Filter::RemoteHost->new($args);
        $zFRH->load();
        $ret = $zFRH->all();
    }
    else {
        $zUser->can_enter_control_section() or return { code => 1 };
        require Unicode::Japanese;
        require Zeromin::Filter::NGWord;
        my $unijp = Unicode::Japanese->new();
        my $zFNGW = Zeromin::Filter::NGWord->new($args);
        $zFNGW->load();
        $ret = $zFNGW->all_in($unijp);
    }

    if ( my $offset = $iRequest->param_int('offset') ) {
        my $item = $iRequest->param_int('item') || 10;
        $ret = $zApp->paging_from_array( $ret, $offset, $item );
    }
    return { code => 0, content => $ret };
}

sub save {
    my ($zApp) = @_;
    my $zUser    = $zApp->user() or return { code => 1 };
    my $iRequest = $zApp->request();
    my $iKernel  = $zApp->kernel();
    my $encoding = $iKernel->get_encoding(1);
    my $args     = ( $zApp->bbs() || $iKernel );
    my $error    = {};
    my $param    = {};

    my $type = $iRequest->param('type');
    if ( $type eq 'ip' ) {
        _validate_ip_param( $zApp, $param, $error ) or return $error;
        require Zeromin::Filter::IP;
        my $zFIP = Zeromin::Filter::IP->new($args);
        my $ip   = $param->{ip};
        my $bbs  = $param->{bbs};
        $zUser->can_add_access() or return { code => 1 };
        $zFIP->load();
        if ( $zFIP->get($ip)->{ip} ) {
            $zApp->logger( 0, 'DUPLICATED DENY IP: %s at %d', [ $ip, $bbs ] );
            return { code => 3 };
        }
        else {
            $zFIP->add( $ip, $bbs );
            $zFIP->save();
            $zApp->logger( 1, 'CREATE DENY IP: %s at %d', [ $ip, $bbs ] );
            return { code => 0, id => $ip };
        }
    }
    elsif ( $type eq 'host' ) {
        $zUser->can_add_access      or return { code => 1 };
        $zUser->can_remove_access() or return { code => 1 };
        require Zeromin::Filter::RemoteHost;
        my $zFRH = Zeromin::Filter::RemoteHost->new($args);
        $zFRH->load();
        my @regexps = split "\n", $iRequest->param('regexp');
        my $update = [];
        for my $regexp (@regexps) {
            $regexp =~ s/[\r\s\t]+//gxms;
            $regexp or next;
            push @$update, $regexp;
        }
        $zFRH->update($update);
        $zFRH->save();
        $zApp->logger( 1, 'UPDATED DENIED HOST LIST' );
        return { code => 0 };
    }
    else {
        _validate_ngword_param( $zApp, $param, $error ) or return $error;
        require Unicode::Japanese;
        require Zeromin::Filter::NGWord;
        my $zFNGW  = Zeromin::Filter::NGWord->new($args);
        my $id     = $iRequest->param('id');
        my $ngword = $zFNGW->get( { id => $id } );
        my $word   = $param->{word};
        my $meth   = $param->{method};
        my $subs   = $param->{subs};
        my $bbs    = $param->{bbs};
        my $unijp  = Unicode::Japanese->new();

        if ( $ngword->{id} ) {
            $zUser->can_edit_ngword() or return { code => 1 };
            $zFNGW->load();
            $zFNGW->set( $id, $meth, $unijp->set( $subs, 'utf8' )->$encoding,
                $bbs );
            $zFNGW->save();
            $zApp->logger(
                1,
                'EDIT NGWORD: %s type is %d and replace to %s at %d',
                [ $word, $meth, $subs, $bbs ],
            );
            { code => 0 };
        }
        else {
            $zUser->can_add_ngword() or return { code => 1 };
            my $word_sjis = $unijp->set( $word, 'utf8' )->$encoding;
            my $subs_sjis = $unijp->set( $subs, 'utf8' )->$encoding;
            $zFNGW->load();
            $zFNGW->add( $word_sjis, $meth, $subs_sjis );
            $zFNGW->save();
            $zApp->logger(
                1,
                'CREATE NGWORD: %s type is %d and replace to %s at %d',
                [ $word, $meth, $subs, $bbs ],
            );
            { code => 0, id => $zFNGW->get( { word => $word_sjis } )->{id} };
        }
    }
}

sub remove {
    my ($zApp) = @_;
    my $zUser    = $zApp->user() or return { code => 1 };
    my $iRequest = $zApp->request();
    my $args     = ( $zApp->bbs() || $zApp->kernel() );
    my $status   = {};
    my $iObject;

    my $type = $iRequest->param('type');
    if ( $type eq 'ip' ) {
        $zUser->can_remove_access() or return { code => 1 };
        $type = 'DENY IP';
        require Zeromin::Filter::IP;
        $iObject = Zeromin::Filter::IP->new($args);
    }
    else {
        $zUser->can_remove_ngword() or return { code => 1 };
        $type = 'NGWORD';
        require Zeromin::Filter::NGWord;
        $iObject = Zeromin::Filter::NGWord->new($args);
    }

    my @ids = $iRequest->param('id');
    $iObject->load();

    for my $id (@ids) {
        if ( $iObject->remove($id) ) {
            $zApp->logger( 1, "REMOVE $type: \%s", [$id] );
            $status->{$id} = 1;
        }
        else {
            $zApp->logger( 0, "TRIED REMOVING INEXIST $type: \%s", [$id] );
            $status->{$id} = 0;
        }
    }
    $iObject->save();

    { code => 0, removed => $status };
}

sub _validate_ip_param {
    my ( $zApp, $param, $error ) = @_;
    my $iRequest = $zApp->request();

    my $ip = $iRequest->param('ip');
    if ( $ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ ) {
        $zApp->logger( 0, 'INVALID IP ADDRESS WAS SET' );
        %{$error} = ( code => 2 );
        return 0;
    }

    $param->{ip}  = $ip;
    $param->{bbs} = Img0ch::Kernel::intval( $iRequest->param('bbs') );
    1;
}

sub _validate_ngword_param {
    my ( $zApp, $param, $error ) = @_;
    my $iRequest = $zApp->request();
    my $encoding = $zApp->kernel()->get_encoding(1);

    my $word = $iRequest->param('entry');
    if ( $word eq '' ) {
        $zApp->logger( 0, 'NO NGWORD WAS SET' );
        %{$error} = ( code => 2 );
        return 0;
    }
    my $meth = $iRequest->param_int('type');
    $meth = { '1' => 1, '2' => 2, '4' => 4 }->{$meth} || 1;

    require Unicode::Japanese;
    my $unijp = Unicode::Japanese->new();
    $param->{bbs}    = $iRequest->param_int('bbs');
    $param->{word}   = $unijp->set( $word, 'utf8' )->$encoding();
    $param->{method} = $meth;
    $param->{subs}
        = $unijp->set( $iRequest->param('to'), 'utf8' )->$encoding();
    1;
}

1;
__END__
