#!/usr/bin/perl -w

# $Id: smbldap-qmail-useradd,v 0.3-2 2004/09/16 01:14:42 Jun Futagawa Exp $
#
#  This code was developped by Jun Futagawa, and based on smblda-tools
#  developped by IDEALX (http://IDEALX.org/) and contributors
#  (their names can be found in that CONTRIBUTORS file).
#
#               Copyright (C) 2004 Jun Futagawa
#
#  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; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
#  USA.

# Purpose of smbldap-qmail-useradd : add/modify/delete an attribute for qmail-ldap entry

use vars qw(@ARGV);

use strict;
use FindBin;
use FindBin qw($RealBin);
use Getopt::Std;
use IO::Handle;
use IO::File;
use lib "$RealBin/";

use smbldap_tools;
use smbldap_qmail_tools;

sub addOptionValue($$$$);
sub addOptionValueNVL($$$$);

my $DIRMAKER = "/var/qmail/control/dirmaker";
my $MESSAGESTORE = "/var/qmail/control/ldapmessagestore";
my $LDAPUID = "/var/qmail/control/ldapuid";
my $LDAPGID = "/var/qmail/control/ldapgid";

my @deliveryModeList = ('(none)', 'noforward', 'nolocal', 'noprogram', 'reply');
my @qmailDotModeList = ('both', 'dotonly', 'ldaponly', 'ldapwithprog', 'none');
my @accountStatusList = ('active', 'noaccess', 'disabled', 'deleted');

#####################

my $fout = new IO::Handle();
$fout->fdopen(fileno(STDOUT), "w") or die "cannot open STDOUT";

my %Options;
my $ok = getopts('vd:u:g:m:a:f:q:c:s:H:S:R:M:P:D:C:A:h?', \%Options);
if ( (!$ok) || (@ARGV < 1) || ($Options{'?'}) ) {
	$fout->printf('%s',
		"Version 0.3-2\n".
		"Usage: $0 [-vdugmafqcsHSRMPDCAh?] username\n".
		"  -v	create virtual mail user\n".
		"  -d	homeDirectory\n".
		"  -u	qmailUID\n".
		"  -g	qmailGID\n".
		"  -m	mail\n".
		"  -a	mailAlternateAddress (multiple attribute)\n".
		"  -f	mailForwardingAddress (multiple attribute)\n".
		"  -q	mailQuotaSize\n".
		"  -c	mailQuotaCount\n".
		"  -s	mailSizeMax\n".
		"  -H	mailHost\n".
		"  -S	mailMessageStore\n".
		"  -R	mailReplyText\n".
		"  -M	deliveryMode: [@deliveryModeList] (multiple attribute)\n".
		"  -P	deliveryProgramPath (multiple attribute)\n".
		"  -D	qmailDotMode: [@qmailDotModeList]\n".
		"  -C	qmailAccountPurge\n".
		"  -A	accountStatus: [@accountStatusList]\n".
		"  -h,?	show this help message\n"
	);
	exit(1);
}

# check user
if ($< != 0) {
	$fout->printf('%s', "You must be root to modify an user\n");
	exit(1);
}

# read only first @ARGV
my $userName = $ARGV[0];

# untaint $userName (can finish with one or two $)
if ($userName =~ /^([\w -.]+\$?)$/) {
	$userName = $1;
} else {
	$fout->printf('%s', "$0: illegal username\n");
	exit(1);
}

# add virtual mail user
if (defined($Options{'v'})) {
	addVirtualQmailUserEntry("uid=$userName,$config{usersdn}", $userName, "$userName\@$config{mailDomain}");
	my $vhomedir = readLine($MESSAGESTORE) . '/' . $userName;
	if (! -e $vhomedir && ! -e $DIRMAKER) {
		if (mkdir $vhomedir) {
			chmod(0700, $vhomedir);
			chown(readLine($LDAPUID), readLine($LDAPGID), $vhomedir);
		} else {
			warn("Unable to create directory: $vhomedir\n");
		}
	}
}

# read user data
my $userEntry = readUserEntry($userName);
if (!defined($userEntry)) {
	$fout->printf('%s',
		"$0: user $userName doesn't exist\n".
		"  create new virtual mail user:	$0 -v [-dugmafqcsHSRMPDCA] username\n"
	);
	exit(1);
}

# get the dn of the user
my $dn = $userEntry->dn();
my @adds;
my @mods;
my @dels;

# initialize mail user
if (!isQmailUser($userName)) {
	addQmailUserAttribute($dn, "$userName\@$config{mailDomain}");
	# get the user information
	my ($login,$pass,$uid,$gid) = getpwnam($userName);
	# add uid and gid for qmail-ldap
	addOptionValueNVL(\@mods, 'u', 'qmailUID', $uid);
	addOptionValueNVL(\@mods, 'g', 'qmailGID', $gid);
}

# add option value
addOptionValue(\@mods, \@dels, 'd', 'homeDirectory');
addOptionValue(\@mods, \@dels, 'u', 'qmailUID');
addOptionValue(\@mods, \@dels, 'g', 'qmailGID');
addOptionValue(\@mods, \@dels, 'm', 'mail');
addOptionValue(\@adds, \@dels, 'a', 'mailAlternateAddress');
addOptionValue(\@adds, \@dels, 'f', 'mailForwardingAddress');
addOptionValue(\@mods, \@dels, 'q', 'mailQuotaSize');
addOptionValue(\@mods, \@dels, 'c', 'mailQuotaCount');
addOptionValue(\@mods, \@dels, 's', 'mailSizeMax');
addOptionValue(\@mods, \@dels, 'H', 'mailHost');
addOptionValue(\@mods, \@dels, 'S', 'mailMessageStore');
addOptionValue(\@mods, \@dels, 'R', 'mailReplyText');
addOptionValue(\@adds, \@dels, 'M', 'deliveryMode');
addOptionValue(\@adds, \@dels, 'P', 'deliveryProgramPath');
addOptionValue(\@mods, \@dels, 'D', 'qmailDotMode');
addOptionValue(\@mods, \@dels, 'C', 'qmailAccountPurge');
addOptionValue(\@mods, \@dels, 'A', 'accountStatus');

# connect to the directory
my $ldap_master = connect_ldap_master();
my $result;
# apply options for single attributes
if (@mods > 0) {
	$result = $ldap_master->modify("$dn", replace => { @mods });
	$result->code && warn "failed to modify entry: ", $result->error;
}
# apply options for multiple attributes
if (@adds > 0) {
	$result = $ldap_master->modify("$dn", add => { @adds });
	$result->code && warn "failed to add entry: ", $result->error;
}
# delete attributes
if (@dels > 0) {
	$result = $ldap_master->modify ("$dn", delete => { @dels });
	$result->code && warn "failed to modify entry: ", $result->error;
}

# close session
$ldap_master->unbind;

# add option value
sub addOptionValue($$$$) {
	my ($list, $dels, $optionName, $attributeName) = @_;
	my $tmp;
	if (defined($tmp = $Options{$optionName})) {
		if ($tmp eq "" && defined $userEntry->get_value($attributeName)) {
			push(@$dels, $attributeName => []);
		} elsif ($tmp ne "") {
			push(@$list, $attributeName => $tmp);
		}
	}
}

# add option value nvl
sub addOptionValueNVL($$$$) {
	my ($list, $optionName, $attributeName, $value) = @_;
	my $tmp;
	if (defined($tmp = $Options{$optionName})) {
		push(@$list, $attributeName => $tmp);
	} else {
		push(@$list, $attributeName => $value);
	}
}

########################################

=head1 NAME

    smbldap-qmail-useradd - add/modify/delete an attribute for qmail-ldap entry

=head1 SYNOPSIS

    smbldap-qmail-useradd
        [-v]
        [-d homeDirectory]
        [-u qmailUID]
        [-g qmailGID]
        [-m mail]
        [-a mailAlternateAddress]
        [-f mailForwardingAddress]
        [-q mailQuotaSize]
        [-c mailQuotaCount]
        [-s mailSizeMax]
        [-H mailHost]
        [-S mailMessageStore]
        [-R mailReplyText]
        [-M deliveryMode]
        [-P deliveryProgramPath]
        [-D qmailDotMode]
        [-C qmailAccountPurge]
        [-A accountStatus]
        username

=head1 DESCRIPTION

    The smbldap-qmail-useradd command creates/modifies/deletes an attribute for qmail-ldap
    entry using the values specified on the command line and the default values
    from the system. The options which apply to the smbldap-qmail-useradd command are

    -v create virtual mail user.

    -d homeDirectory The value of the home directory.

    -u qmailUID The value of system uid for qmail-ldap.

    -g qmailGID The value of system gid for qmail-ldap.

    -m mail The value of the mail address.

    -a mailAlternateAddress The value of the alternate mail address. (support multiple attribute)

    -f mailForwardingAddress The value of the forwarding mail address. (support multiple attribute)

    -q mailQuotaSize The value of the max mailbox size.

    -c mailQuotaCount The value of the max amount of mail.

    -s mailSizeMax The value of the max one mail size.

    -H mailHost The value of the mail host address.

    -S mailMessageStore The value of the mail store directory.

    -R mailReplyText The value of the reply message.

    -M deliveryMode The value of the mail delivery mode. [(none) noforward nolocal noprogram reply] (support multiple attribute)

    -P deliveryProgramPath The value of the program path. (support multiple attribute)

    -D qmailDotMode The value of the .qmail mode. [both dotonly ldaponly ldapwithprog none].

    -C qmailAccountPurge The value of the epoch time.

    -A accountStatus The value of the forwarding mail address. [active noaccess disabled deleted].

=cut

#'
