#!%PERL%
# Copyright (c) vhffs project and its contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions 
# are met:
#
# 1. Redistributions of source code must retain the above copyright 
#   notice, this list of conditions and the following disclaimer.
#2. Redistributions in binary form must reproduce the above copyright
#   notice, this list of conditions and the following disclaimer in 
#   the documentation and/or other materials provided with the 
#   distribution.
#3. Neither the name of vhffs nor the names of its contributors 
#   may be used to endorse or promote products derived from this 
#   software without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
#FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
#COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
#INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
#BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
# POSSIBILITY OF SUCH DAMAGE.

use strict;
use utf8;

package Vhffs::Panel::DNS;

use DBI;
use HTML::Template;
use locale;
use Locale::gettext;
use CGI;
use CGI::Session;
use Vhffs::User;
use Vhffs::Main;
use Vhffs::Panel::Main;
use Vhffs::Constants;
use Vhffs::Acl;
use Vhffs::Services::DNS;


sub search
{
    my ($main, $name) = @_;
    my $sql;
    my $dns = [];
    my @params;

    if( defined $name ) {
        $sql = 'SELECT ns.domain, g.groupname, o.state FROM vhffs_dns ns INNER JOIN vhffs_object o ON o.object_id = ns.object_id INNER JOIN vhffs_groups g ON g.gid = o.owner_gid WHERE ns.domain LIKE ?';
        push(@params, '%'.lc($name).'%');
    } else {
        $sql = 'SELECT ns.domain, g.groupname, o.state FROM vhffs_dns ns INNER JOIN vhffs_object o ON o.object_id = ns.object_id INNER JOIN vhffs_groups g ON g.gid = o.owner_gid';
    }

    my $dbh = $main->get_db_object();
    my $sth = $dbh->prepare( $sql ) or return undef;

    return undef unless($sth->execute(@params));

    while(my $d = $sth->fetchrow_hashref('NAME_lc')) {
        $d->{state} = Vhffs::Functions::status_string_from_status_id($d->{state});
        push(@$dns, $d);
    }
    return $dns;
}



sub create_dns
{
    my ( $main , $dns_name, $description , $user , $group ) = @_;
    return undef if( ! defined $user );
    return undef if( ! defined $group );

    my $dns = Vhffs::Services::DNS::create( $main , $dns_name, $description, $user , $group );
	return undef if( ! defined $dns );

    return undef if ( Vhffs::Acl::add_acl( $user , $dns , Vhffs::Constants::ACL_DELETE , $main ) < 0 );
    return undef if( Vhffs::Acl::add_acl( $group , $dns , Vhffs::Constants::ACL_VIEW , $main ) < 0 );

    return $dns;
}


#Returns an array which contains | domain_name | object_id (from DNS)
sub getall_dns_per_user
{
	my ( $user , $main ) = @_ ;

	return undef if ( ! defined $user );

	my $query = "SELECT ns.domain, ns.object_id FROM vhffs_dns ns, vhffs_acl acl ,vhffs_users WHERE vhffs_users.object_id=acl.oid_src AND acl.oid_dst=ns.object_id AND vhffs_users.username='".$user->{'username'}."'";

	my $request = $main->{'db'}->prepare( $query ) or return -1;

	return undef if ( $request->execute() <= 0);

	return( $request->fetchrow_arrayref() );	
}

=pod

=head2 getall_per_group

    $dns = Vhffs::Panel::Dns::getall_per_group($vhffs, $gid);

Returns an array of hashrefs (oid, displayname, active, state (localized string)) of all DNS owned by
a given group.

=cut


sub getall_per_group
{
    my ( $main, $gid ) = @_;

    my $dbh = $main->get_db_object;
    my $sql = 'SELECT ns.object_id AS oid, ns.domain AS displayname, o.state FROM vhffs_dns ns INNER JOIN vhffs_object o ON ns.object_id = o.object_id WHERE o.owner_gid = ? ORDER BY ns.domain';
    my $sth = $dbh->prepare($sql) or return -1;
    $sth->execute($gid) or return -2;
    my $dns = [];
    while(my $d = $sth->fetchrow_hashref) {
        $d->{active} = ($d->{state} == Vhffs::Constants::ACTIVATED);
        $d->{refused} = ($d->{state} == Vhffs::Constants::VALIDATION_REFUSED);
        $d->{state} = Vhffs::Functions::status_string_from_status_id($d->{state});
        push @$dns, $d;
    }
    return $dns;
}

=pod

=head2 delete_record

    eval { Vhffs::Panel::DNS::delete_record($dns, $id, $type); };
    if($@) {
        print "An error occured: $@\n";
    } else {
        print "$type Record deleted\n";
    }

=cut

sub delete_record {
    my ($dns, $id, $type) = @_;
    die() unless(defined $dns && defined $id && defined $type);
    die(gettext('You cannot delete NS records on origin')."\n") if($type eq 'NS' and defined $dns->{NS}->{$id}->{name} and $dns->{NS}->{$id}->{name} eq '@');
    my $rval = $dns->delete_record($id, $type);
    return 1 if($rval > 0);
    die(gettext('Invalid record')."\n") if($rval == -1);
    die(gettext('Record type doesn\'t exists')."\n") if($rval == -2);
    die(gettext('Record does not exists')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n");
}



=pod

=head2 add_a

    eval { Vhffs::Panel::DNS::add_a($dns, $redirect, $name, $ip); };
    if($@) {
        print "An error occured: $@\n";
    } else {
        print "A Record added\n";
    }

Add a new A resource record to $dns. If $redirect is true, $name points
to default address defined in configuration, else, it points on $ip.

=cut

sub add_a {
    my ($dns, $redirect, $name, $ip) = @_;
    die() unless(defined $dns && defined $redirect && defined $name && defined $ip);
    my $rval;
    if($redirect) {
        $rval = $dns->add_a($name);
    } else {
        $rval = $dns->add_a($name, $ip);
    }
    return 1 if($rval > 0);
    die(gettext('Invalid prefix')."\n") if($rval == -1);
    die(gettext('Prefix already exists')."\n") if($rval == -2);
    die(gettext('Unable to find default redirection address, please contact administrators')."\n") if($rval == -3);
    die(gettext('Invalid IP address')."\n") if($rval == -4);
    die(gettext('Database error')."\n") if($rval == -5);
    die(gettext('Unknown error')."\n");
}

sub update_a {
    my ($dns, $id, $ip) = @_;
    die() unless(defined $dns && defined $id && defined $ip);
    my $rval = $dns->update_a($id, $ip);
    return 1 if($rval > 0);
    die(gettext('Invalid record')."\n") if($rval == -1);
    die(gettext('Record does not exists')."\n") if($rval == -2);
    die(gettext('Invalid IP address')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n");
}

sub add_aaaa {
    my ($dns, $redirect, $name, $ip) = @_;
    die() unless(defined $dns && defined $redirect && defined $name && defined $ip);
    my $rval;
    if($redirect) {
        $rval = $dns->add_aaaa($name);
    } else {
        $rval = $dns->add_aaaa($name, $ip);
    }
    return 1 if($rval > 0);
    die(gettext('Invalid prefix')."\n") if($rval == -1);
    die(gettext('Prefix already exists')."\n") if($rval == -2);
    die(gettext('Unable to find default redirection address, please contact administrators')."\n") if($rval == -3);
    die(gettext('Invalid IP v6 address')."\n") if($rval == -4);
    die(gettext('Database error')."\n") if($rval == -5);
    die(gettext('Unknown error')."\n");
}

sub update_aaaa {
    my ($dns, $id, $ip) = @_;
    die() unless(defined $dns && defined $id && defined $ip);
    my $rval = $dns->update_aaaa($id, $ip);
    return 1 if($rval > 0);
    die(gettext('Invalid record')."\n") if($rval == -1);
    die(gettext('Record does not exists')."\n") if($rval == -2);
    die(gettext('Invalid IP address')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n");
}

sub add_mx {
    my ($dns, $name, $host, $priority) = @_;
    die() unless(defined $dns && defined $name && defined $host && defined $priority);
    my $rval = $dns->add_mx( $name, $host, $priority);
    return 1 if($rval > 0);
    die(gettext('Invalid hostname')."\n") if($rval == -1);
    die(gettext('Invalid priority')."\n") if($rval == -2);
    die(gettext('An MX record with the same name already exists for this domain')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Invalid prefix')."\n") if($rval == -5);
    die(gettext('Unknown error')."\n");
}

sub update_mx {
    my ($dns, $id, $host) = @_;
    die() unless(defined $dns && defined $id && defined $host);
    my $rval = $dns->update_mx($id, $host);
    return 1 if($rval > 0);
    die(gettext('Invalid record')."\n") if($rval == -1);
    die(gettext('Record does not exists')."\n") if($rval == -2);
    die(gettext('Invalid host')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n"),;
}

sub add_ns {
    my ($dns, $name, $host) = @_;
    die() unless(defined $dns && defined $name && defined $host);
    die(gettext('You cannot add NS records on origin')."\n") if($name eq '@');
    my $rval = $dns->add_ns($name, $host);
    return 1 if($rval > 0);
    die(gettext('Invalid hostname')."\n") if($rval == -1);
    die(gettext('An NS record with the same name already exists for this domain')."\n") if($rval == -2);
    die(gettext('Database error')."\n") if($rval == -3);
    die(gettext('Invalid prefix')."\n") if($rval == -5);
    die(gettext('Unknown error')."\n");
}

sub update_cname {
    my ($dns, $id, $dest) = @_;
    die() unless(defined $dns && defined $id && defined $dest);
    my $rval = $dns->update_cname($id, $dest);
    return 1 if($rval > 0);
    die(gettext('Invalid record')."\n") if($rval == -1);
    die(gettext('Record does not exists')."\n") if($rval == -2);
    die(gettext('Invalid destination')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n");

}

sub add_cname {
    my ($dns, $name, $dest) = @_;
    die() unless(defined $dns && defined $name && defined $dest);
    my $rval = $dns->add_cname($name, $dest);
    return 1 if($rval > 0);
    die(gettext('Invalid alias')."\n") if($rval == -1);
    die(gettext('Invalid destination host')."\n") if($rval == -2);
    die(gettext('A CNAME, A or AAAA record with the same name already exists for this domain')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n");
}

sub add_srv {
    my ($dns, $name, $proto, $svc, $host, $port, $priority, $weight) = @_;
    die() unless(defined $dns && defined $name && defined $proto && defined $svc && defined $host && defined $port && defined $priority && defined $weight);
    my $rval = $dns->add_srv($name, $proto, $svc, $host, $port, $priority, $weight);
    return 1 if($rval > 0);
    die(gettext('Invalid protocol syntax')."\n") if($rval == -1);
    die(gettext('Invalid service syntax')."\n") if($rval == -2);
    die(gettext('Invalid destination domain name')."\n") if($rval == -3);
    die(gettext('Invalid port')."\n") if($rval == -4);
    die(gettext('Invalid priority')."\n") if($rval == -5);
    die(gettext('Invalid weight')."\n") if($rval == -6);
    die(gettext('Invalid record')."\n") if($rval == -7);
    die(gettext('This host is already registered for this service')."\n") if($rval == -8);
    die(gettext('Database error')."\n") if($rval == -9);
    die(gettext('Unknown error')."\n");
}

sub update_srv {
    my ($dns, $id, $host, $port, $priority, $weight) = @_;
    die() unless(defined $dns && defined $host && defined $port && defined $priority && defined $weight);
    my $rval = $dns->update_srv($id, $host, $port, $priority, $weight);
    return 1 if($rval > 0);
    die(gettext('Invalid record')."\n") if($rval == -1);
    die(gettext('Record does not exists')."\n") if($rval == -2);
    die(gettext('Invalid destination domain name')."\n") if($rval == -3);
    die(gettext('Invalid port')."\n") if($rval == -4);
    die(gettext('Invalid priority')."\n") if($rval == -5);
    die(gettext('Invalid weight')."\n") if($rval == -6);
    die(gettext('Database error')."\n") if($rval == -7);
    die(gettext('Unknown error')."\n");
}

sub add_txt {
    my ($dns, $name, $txt) = @_;
    die() unless(defined $dns && defined $name && defined $txt);
    my $rval = $dns->add_txt($name, $txt);
    return 1 if($rval > 0);
    die(gettext('Invalid prefix')."\n") if($rval == -1);
    die(gettext('Text can\'t be empty')."\n") if($rval == -2);
    die(gettext('A TXT record with the same name already exists for this domain')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n");
}

sub update_txt {
    my ($dns, $id, $txt) = @_;
    die() unless(defined $dns && defined $id && defined $txt);
    my $rval = $dns->update_txt($id, $txt);
    return 1 if($rval > 0);
    die(gettext('Invalid record')."\n") if($rval == -1);
    die(gettext('Record does not exists')."\n") if($rval == -2);
    die(gettext('Text can\'t be empty')."\n") if($rval == -3);
    die(gettext('Database error')."\n") if($rval == -4);
    die(gettext('Unknown error')."\n"),;
}

1;
