#!/usr/bin/perl
#
# Simple script to set quota of a specific mailbox on cyrus.
# License : GPL v2.0 (see www.gnu.org)
# last modified : 2004/01/16
use warnings;
use strict;
use Getopt::Long;
use Cyrus::IMAP::Admin;

my ($mailhost, $newquota, @mailboxlist, $admin, $pass, $mech);

# valeurs par défaut:
my $default_admin = "cyradm";
my $default_mailhost = "localhost";
my $default_mech = "login";
my $default_newquota = "50M";

# Fonctions:
# Rapport mis en forme
# (&Report($quotaroot, \@oldqstate, \@qstate))
sub Report {
    my $quotaroot = $_[0];
    my $old = $_[1];
    my $new = $_[2];

    my $info_head = "quotaroot: $quotaroot\n";
    my $info_line1 = "  old quota: $old->[1]k total\n";
    my $info_line2 = "  new quota: $new->[1]k total, $new->[0]k used\n";
    my $separateur;

    my $length_head = length($info_head);
    my $length_line1 = length($info_line1);
    my $length_line2 = length($info_line2);
    
    $separateur = "-" x $length_head if (($length_head >= $length_line1) && ($length_head >= $length_line2));
    $separateur = "-" x $length_line1 if (($length_line1 > $length_head) && ($length_line1 >= $length_line2));
    $separateur = "-" x $length_line2 if (($length_line2 > $length_line1) && ($length_line2 >= $length_head));
    
    print "\n" . $separateur . "\n";
    print $info_head;
    print $info_line1;
    print $info_line2;
    print $separateur . "\n";
}

# Usage
sub Usage {
    print <<EOF;
This script set a quota on one or more cyrus mailboxes.
Usage: $0 [-h|--hostname <host>] [-u|--user <user>] [-p|--password <password>] [-m|--mech <mechanism>] <mailboxlist> <quota>

where: 
<host> is the cyrus host to connect to (default to $default_mailhost)
<user> is the admin user (default to $default_admin)
<password> is the cyrus admin password
<mechanism> is the authentification mechanism (default to $default_mech)
<mailboxlist> is a comma-separated list of mailboxes
<quota> is either a number alone (kilobytes), or a number followed by a letter (k or K or m or M or g or G) (default to $default_newquota).
exemple:

$0 -p'secret!' 'user/toto,user/tata,user/titi' 100M
$0 -p'secret!' 'user/tom'

EOF
    exit 1;
}

# interprétation ligne de commande

GetOptions( 
	    "h|hostname=s"	=> \$mailhost,
	    "u|user=s"		=> \$admin,
	    "p|password=s"	=> \$pass,
	    "m|mech=s"		=> \$mech,
);

if ($ARGV[1]) {
    $newquota = $ARGV[1];
    @mailboxlist = split (/,/, $ARGV[0]);
    $mailhost = $default_mailhost unless ($mailhost);
    $admin = $default_admin unless ($admin);
    $newquota = $default_newquota unless ($newquota);
    $mech = $default_mech unless ($mech);
} else {
    &Usage
}

# quota formatting:
if ($newquota =~ /^(\d+)([mkg]?)$/i) {
    my $numb = $1;
    my $letter = $2;
    if ($letter =~ /^m$/i) {
	$newquota = $numb * 1024;
    } elsif ($letter =~ /^g$/i) {
	$newquota = $numb * 1024 * 1024;
    } elsif ($letter =~ /^k?$/i) {
	$newquota = $numb;
    } else {
	die "malformed quota: $newquota (must be at least one digit eventually followed by k, K, m, M, g or G\n";
    }
}

# connexion/auth
my $cyradm = Cyrus::IMAP::Admin->new($mailhost);
$cyradm->authenticate(
		-mechanism => $mech, 
		-user => $admin,
		-password => $pass,
);
die $cyradm->error if $cyradm->error;


# positionnement du quota
# (la commande listquota est une horreur à manier)
foreach my $mailbox (@mailboxlist) {
    my %oldqstate = $cyradm->listquota($mailbox); # warning: if several quotaroot by mb, will be wrong, I guess...
    $cyradm->setquota($mailbox, 'STORAGE', $newquota);
    die "Encountered an error when trying to set quota $newquota on $mailbox :\n
    $cyradm->error\n" if $cyradm->error;
    my %qstate = $cyradm->listquota($mailbox);
    my @oldstore = $oldqstate{STORAGE};
    my @store = $qstate{STORAGE};
    &Report($mailbox, $oldqstate{STORAGE}, $qstate{STORAGE});
}


