# vim: set cindent expandtab ts=4 sw=4:
#
# Copyright (c) 1998-2005 Chi-Keung Ho. All rights reserved.
#
# This programe 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.
# 
# ExtMan - web interface to manage virtual accounts
# $Id$
package Ext::MgrApp::User;
use strict;
use Exporter;

use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter Ext::MgrApp);
use POSIX qw(strftime);
use Ext::Utils; # import url2str
use Ext::MgrApp;
use vars qw($lang_charset %lang_user $default_expire);
use Ext::Lang;

sub init {
    my $self = shift;
    $self->SUPER::init(@_);
    return unless($self->valid||$self->permit);

    $self->add_methods(add_user => \&add_user);
    $self->add_methods(edit_user => \&edit_user);
    $self->add_methods(save_user => \&save_user);
    $self->add_methods(delete_user => \&delete_user);
    $self->{default_mode} = 'edit_user';

    $default_expire = $self->cvt2expire(strftime("%Y-%m-%d %H:%M:%S", localtime));
    $self->_initme;
    $self;
}

sub _initme {
    initlang($_[0]->{sysconfig}->{'SYS_LANG'}, __PACKAGE__);
    $_[0]->{tpl}->assign( lang_charset => $lang_charset );
    $_[0]->{tpl}->assign( \%lang_user );
}

sub add_user {
    my $self = shift;
    my $tpl = $self->{tpl};
    my $mgr = $self->{backend};
    my $q = $self->{query};
    my $sys = $self->{sysconfig};
    my $domain = lc $q->cgi('domain');
    my $domains = [];

    if ($ENV{USERTYPE} eq 'admin') {
        my $alldomain = $mgr->get_domains_list;
        foreach my $d ( @$alldomain ) {
            push @$domains, $d->{domain};
        }
    } else {
        my $pm = $mgr->get_manager_info($ENV{USERNAME});
        $domains = $pm->{domain};
    }

    if (!$domain) {
        $domain = $domains->[0]; # the first?
    }

    my $info = $mgr->get_domain_info($domain);

    if (keys %$info) {
        my $multiplier = $self->{sysconfig}->{SYS_QUOTA_MULTIPLIER} || '1048576';

        if ($info->{default_expire}) {
            $default_expire = $self->cvt2expire(
                strftime("%Y-%m-%d %H:%M:%S", localtime),
                $info->{default_expire},
            );
        }
        if ($info->{default_quota}) {
            $info->{default_quota} = $self->quota2num($info->{default_quota})/$multiplier;
        }
        if ($info->{default_ndquota}) {
            $info->{default_ndquota} = $self->quota2num($info->{default_ndquota})/$multiplier;
        }
    }

    $tpl->assign(
        HAVE_USER => 1,
        NEWADD => 1,
        EXPIRE => $default_expire,
        ACTIVE => 1, 
        QUOTA => $info->{default_quota} || $sys->{SYS_USER_DEFAULT_QUOTA} || '0',
        NDQUOTA => $info->{default_ndquota} || $sys->{SYS_USER_DEFAULT_NDQUOTA} || '0',
        UID => $sys->{SYS_DEFAULT_UID},
        GID => $sys->{SYS_DEFAULT_GID},
    );

    for my $s ( split(/,/, $sys->{SYS_USER_ROUTING_LIST}) ) {
        $s =~ s/\s+//;
        $tpl->assign(
            'LOOP_ROUTING_LIST',
            MAILHOST => $s,
        );
    }

    if (keys %$info) {
        for my $s (qw(smtpd smtp webmail netdisk imap pop3)) {
            $tpl->assign( "SERVICES_$s" => $info->{"disable".$s} ? 0 : 1 );
            $tpl->assign( "NOCHK_$s" => $info->{"disable".$s} ? 1 : 0 )
                if ($ENV{USERTYPE} ne 'admin');
        }
    } else {
        for my $s ( split(/,/, $sys->{SYS_DEFAULT_SERVICES}) ) {
            $tpl->assign( "SERVICES_$s" => 1 );
        }
    }

    if ($domains) {
        $domains = [$domains] unless (ref $domains);
        foreach my $vd ( @$domains ) {
            $tpl->assign(
                'LOOP_DOMAIN',
                DOMAIN => $vd,
                DOMAIN_CHK => ($vd eq lc $domain ? 1 : 0),
            );
        }
    } else {
        # no permission or not assign domain
        $tpl->assign(NOPERM => 1);
        $tpl->assign(HAVE_USER => 0);
    }
}

sub edit_user {
    my $self = shift;
    my $tpl = $self->{tpl};
    my $mgr = $self->{backend};
    my $q = $self->{query};
    my $multiplier = $self->{sysconfig}->{SYS_QUOTA_MULTIPLIER} || '1048576';
    my $user = $q->cgi('user') || $q->cgi('username').'@'.$q->cgi('domain');
    my $ui = $mgr->get_user_info($user);

    return 0 unless($ui);

    # permission validation
    unless ($self->valid_perm($ui->{domain})) {
        $self->error('Access denied');
        return 0;
    }

    my ($uname) = ($ui->{mail} =~ m!(.*)@.*!);

    $tpl->assign(HAVE_USER => 1);
    $tpl->assign(
        MAIL => $ui->{mail},
        UNAME => $uname,
        NAME => $ui->{cn} || $ui->{username},
        DOMAIN => $ui->{domain},
        MAILHOST => $ui->{mailhost},
        UID => $ui->{uidnumber},
        GID => $ui->{gidnumber},
        EXPIRE => $ui->{expire},
        PASSWD => "",
        QUOTA => $self->quota2num($ui->{quota})/$multiplier,
        NDQUOTA => $self->quota2num($ui->{netdiskquota})/$multiplier,
        ACTIVE => $ui->{active},
        DISABLEPWDCHANGE => $ui->{disablepwdchange},
    );

    my $info = $mgr->get_domain_info($ui->{domain});
    for my $srv (qw(smtpd smtp webmail netdisk imap pop3)) {
        $tpl->assign( 'SERVICES_'.$srv => $ui->{"disable$srv"} ? 0 : 1 );
        $tpl->assign( 'NOCHK_'.$srv => $info->{"disable$srv"} ? 1 : 0 )
            if ($ENV{USERTYPE} ne 'admin');
    }
}

sub save_user {
    my $self = shift;
    my $tpl = $self->{tpl};
    my $mgr = $self->{backend};
    my $q = $self->{query};
    my $multiplier = $self->{sysconfig}->{SYS_QUOTA_MULTIPLIER} || '1048576';
    my ($user, $domain) = (lc $q->cgi('username'), lc $q->cgi('domain'));

    # permission validation
    unless ($self->valid_perm($domain)) {
        $self->error('Access denied');
        return 0;
    }

    if (!$self->sanity_username($user)) {
        $self->error('Bad username');
        return 0;
    }

    if ($mgr->get_user_info("$user\@$domain")) {
        if ($q->cgi('newadd')) {
            $tpl->assign(ERROR => $lang_user{'user_exist'});
            $self->add_user;
            return 0;
        }else {
            # save the change
            my $pwd1 = $q->cgi('passwd1');
            my $pwd2 = $q->cgi('passwd2');

            if ($pwd1 && $pwd2) {
                if ($pwd1 ne $pwd2) {
                    # pwd1 != pwd2, password modification fail, abort
                    $tpl->assign(ERROR => $lang_user{'errinput_passwd'});
                    return 0;
                }
            }

            if (!$self->valid_time($q->cgi('expire'))) {
                $tpl->assign(ERROR => $lang_user{'err_time'});
                $self->edit_user;
                return;
            }

            my $old = $mgr->get_user_info("$user\@$domain");
            my $oldquota = $self->quota2num($old->{quota});
            my $oldndquota = $self->quota2num($old->{netdiskquota});
            my $newquota = $multiplier*$q->cgi('quota'); # number
            my $newndquota = $multiplier*$q->cgi('netdiskquota'); # number

            #die "$newndquota $oldndquota\n";
            my $rc = $self->domain_overusage(
                domain => $domain,
                quota => ($newquota - $oldquota > 0 ? $newquota - $oldquota : 0 ),
                ndquota => ($newndquota - $oldndquota > 0 ? $newndquota - $oldndquota : 0 ),
            );

            $rc = $mgr->modify_user(
                user => "$user\@$domain",
                domain => $domain,
                cn => $q->cgi('cn'),
                uidnumber => $q->cgi('uid'),
                gidnumber => $q->cgi('gid'),
                expire => $q->cgi('expire'),
                passwd => $pwd1,
                quota => $self->num2quota($multiplier*$q->cgi('quota')),
                netdiskquota => $self->num2quota($multiplier*$q->cgi('netdiskquota')),
                active => $q->cgi('active'),
                disablepwdchange => $q->cgi('disablepwdchange') ? 1 : 0,
                disablesmtpd => $q->cgi('SERVICES_smtpd') ? 0 : 1,
                disablesmtp => $q->cgi('SERVICES_smtp') ? 0 : 1,
                disablewebmail => $q->cgi('SERVICES_webmail') ? 0 : 1,
                disablenetdisk => $q->cgi('SERVICES_netdisk') ? 0 : 1,
                disablepop3 => $q->cgi('SERVICES_pop3') ? 0 : 1,
                disableimap => $q->cgi('SERVICES_imap') ? 0 : 1,
            ) unless ($rc);

            if ($rc) {
                $tpl->assign(ERROR => sprintf($lang_user{'modify_fail'}, $q->cgi('username')).$rc);
            }else {
                $tpl->assign(SUCCESS => sprintf($lang_user{'modify_ok'}, $q->cgi('username')));
            }
            $self->edit_user;
        }
    } else {
        # no such user
        if ($q->cgi('newadd')) {
            # new add user
            my $pwd1 = $q->cgi('passwd1');
            my $pwd2 = $q->cgi('passwd2');

            # include all possible state:
            # 1) pwd1 null, pwd2 not null
            # 2) pwd2 null, pwd1 not null
            # 3) pwd2 and pwd1 not null, but not eq
            if ($pwd1 ne $pwd2) {
                $tpl->assign(ERROR => $lang_user{'errinput_passwd'});
                return 0;
            }

            if (!$self->valid_time($q->cgi('expire'))) {
                $tpl->assign(ERROR => $lang_user{'err_time'});
                $self->add_user;
                return;
            }

            my $rc = $self->domain_overusage(
                domain => $domain,
                quota => $multiplier*$q->cgi('quota'),
                user => 1, # new add, must exists
                ndquota => $multiplier*$q->cgi('netdiskquota'),
            );

            my $d_hashdir = $self->get_domain_hashdir($domain);
            my $u_hashdir = $self->gen_user_hashdir;
            my $path;
            if ($self->{sysconfig}->{SYS_ISP_MODE} eq 'yes') {
                $path = ($d_hashdir ? "$d_hashdir/" : "").
                        "$domain/" .($u_hashdir? "$u_hashdir/" : "").
                        $user;
            } else {
                $path = "$domain/$user";
            }

            $rc = $mgr->add_user(
                mail => "$user\@$domain",
                domain => $domain,
                uid => $user,
                cn => $q->cgi('cn'),
                uidnumber => $q->cgi('uid'),
                gidnumber => $q->cgi('gid'),
                # new user attributes here
                create => strftime("%Y-%m-%d %H:%M:%S", localtime),
                expire => $q->cgi('expire'),
                passwd => $pwd1,
                quota => $self->num2quota($multiplier*$q->cgi('quota')),
                mailhost => $q->cgi('mailhost'),
                maildir => "$path/Maildir/",
                homedir => $path,
                netdiskquota => $self->num2quota($multiplier*$q->cgi('netdiskquota')),
                active => $q->cgi('active'),
                disablepwdchange => $q->cgi('disablepwdchange') ? 1 : 0,
                disablesmtpd => $q->cgi('SERVICES_smtpd') ? 0 : 1,
                disablesmtp => $q->cgi('SERVICES_smtp') ? 0 : 1,
                disablewebmail => $q->cgi('SERVICES_webmail') ? 0 : 1,
                disablenetdisk => $q->cgi('SERVICES_netdisk') ? 0 : 1,
                disablepop3 => $q->cgi('SERVICES_pop3') ? 0 : 1,
                disableimap => $q->cgi('SERVICES_imap') ? 0 : 1,
            ) unless ($rc);

            if ($rc) {
                $tpl->assign(ERROR => sprintf($lang_user{'add_fail'}, "$user\@$domain").$rc);
            } else {
                $tpl->assign(SUCCESS => sprintf($lang_user{'add_ok'}, "$user\@$domain"));
                my $dir = $self->{sysconfig}->{SYS_CONFIG};
                my $base = $self->{sysconfig}->{SYS_MAILDIR_BASE};
                system("$dir/tools/maildirmake.pl $base/$path/Maildir/");
            }
            $self->add_user;
        } else {
            $tpl->assign(ERROR => $lang_user{'no_such_user'});
        }
    }
}

sub delete_user {
    my $self = shift;
    my $tpl = $self->{tpl};
    my $q = $self->{query};
    my $mgr = $self->{backend};
    my $user = lc $q->cgi('user');

    my ($domain) = ($user =~ m!.*@(.*)!);
    # permission validation
    unless ($self->valid_perm($domain)) {
        $self->error('Access denied');
        return 0;
    }

    if ($mgr->get_user_info($user)) {
        my $rc = $mgr->delete_user($user);
        if ($rc) {
            $tpl->assign(ERROR => "Delete fail!");
        } else {
            $tpl->{noprint} = 1;
            $self->{redirect} = url2str($q->cgi('url'));
        }
    } else {
        $tpl->assign(ERROR => $lang_user{'no_such_user'});
    }
}

sub pre_run { 1 }

sub post_run {
    my $template = $_[0]->{query}->cgi('screen') || 'edit_user.html';
    $_[0]->{tpl}->process($template);
    $_[0]->{tpl}->print;
}

1;


syntax highlighted by Code2HTML, v. 0.9.1