#!/usr/bin/env perl

## v0.11

use strict;
use DBI;

my($db_host)            = '127.0.0.1';
my($db_name)            = 'postfixadmin';
my($db_user)            = 'postfixadmin';
my($db_password)        = 'XXXXXXXXXX';

# Base virtual domain
my($default_realm) = "domain.tld";
my($debug) = 1;
my($debug) = 0;

my($dsn) = "DBI:mysql:$db_name:$db_host";

my($dbh) = DBI->connect($dsn, $db_user, $db_password, { RaiseError => 0 });

unless ($dbh) {
	print(STDERR "Couldn't connect to db '$db_name' on host '$db_host' as user '$db_user': ".$DBI::errstr."\n");
} else {

	my($user);
	print('user@domain: ');
	if ($ARGV[0]) {
		$user = $ARGV[0];
	} else {
		chomp($user = <STDIN>);
	}
	$user = lc($user);
	$user .= "\@$default_realm" unless ($user =~ /\@/);
	print("$user\n") if ($ARGV[0]);

	my($word1, $word2);
	if ($ARGV[1]) {
		$word1 = $ARGV[1];
	} else {
		while (! $word1) {
			print "Password: ";
			system "stty -echo";
			chomp($word1 = <STDIN>);
			system "stty echo";
			print("\n");

			print "Retype password: ";
			system "stty -echo";
			chomp($word2 = <STDIN>);
			system "stty echo";
			print("\n");

			if ($word1 ne $word2) {
				print("Sorry, passwords do not match\n");
				$word1 = '';
			}
		}
	}
	my($new_password);
	if ($word1 =~ /^(\{[A-Z\d]+(-CRYPT)?\})?\$(1|2|2a|2b|2x|2y|5|6)\$.+\$/) {
		$new_password = $word1;
	} else {
		my($salt) = '';
		$salt .= ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64] while (length($salt) < 8 + rand(9));

##		$new_password = crypt($word1, "\$1\$${salt}\$");
#		$new_password = crypt($word1, "\$5\$${salt}\$");
		$new_password = crypt($word1, "\$6\$${salt}\$");
	}

	my($sth_get_user) = $dbh->prepare(qq{
SELECT * FROM mailbox WHERE username=?
});

	unless ($sth_get_user) {
		print(STDERR "Couldn't prepare query: ".$dbh->errstr()."\n");
	} else {
		unless ($sth_get_user->execute($user)) {
			print(STDERR "Couldn't execute query: ".$sth_get_user->errstr()."\n");
		} else {
			if (my @data = $sth_get_user->fetchrow_array()) {
				my($sth_change_passwd) = $dbh->prepare(qq{
UPDATE mailbox
SET
    password=?,
    modified=NOW()
WHERE
    username=?
});
				unless ($sth_change_passwd) {
					print(STDERR "Couldn't prepare query: ".$dbh->errstr()."\n");
				} else {
					unless ($sth_change_passwd->execute($new_password, $user)) {
						print(STDERR "Couldn't execute query: ".$sth_change_passwd->errstr()."\n");
					}
				}
			} else {
				my($fullname);
				if ($ARGV[2]) {
					$fullname = $ARGV[2];
				} else {
					print("Full name: ");
					chomp($fullname = <STDIN>);
				}
				$fullname = $user unless ($fullname);

				my($sth_add_user) = $dbh->prepare(qq{
INSERT `mailbox`
    (`username`, `password`, `name`, `maildir`, `local_part`, `domain`, `created`, `modified`)
VALUES
    (?, ?, ?, ?, ?, ?, NOW(), NOW())
});
				unless ($sth_add_user) {
					print(STDERR "Couldn't prepare query: ".$dbh->errstr()."\n");
				} else {
					my($sth_add_alias) = $dbh->prepare(qq{
INSERT `alias`
    (`address`, `goto`, `domain`, `created`, `modified`)
VALUES
    (?, ?, ?, NOW(), NOW())
});
					unless ($sth_add_alias) {
						print(STDERR "Couldn't prepare query: ".$dbh->errstr()."\n");
					} else {
						my($mailbox, $domain) = ($user =~ /^(.+)\@(.+)$/);
						unless ($sth_add_user->execute($user, $new_password, $fullname, "$domain/$mailbox/", $mailbox, $domain)) {
							print(STDERR "Couldn't execute query: ".$sth_add_user->errstr()."\n");
						} else {
							unless ($sth_add_alias->execute($user, $user, $domain)) {
								print(STDERR "Couldn't execute query: ".$sth_add_alias->errstr()."\n");
							}
						}
					}
				}
			}
			$sth_get_user->finish();
		}
	}
	unless ($dbh->disconnect()) {
		print(STDERR "Couldn't disconnect from db '$db_name' on host '$db_host': ".$DBI::errstr."\n");
	}
}
