John Dennis 38f226
#!/usr/bin/perl
John Dennis 38f226
use Cyrus::IMAP::Admin;
John Dennis 38f226
John Dennis 38f226
# This script was created by Kevin J. Menard, Jr. <kmenard@wpi.edu>.
John Dennis 38f226
# It requires root privileges to write to a file in /etc.  Best use is
John Dennis 38f226
# to set this up as cron job.  Works for me.  Hope it does for you.  
John Dennis 38f226
# Any questions/complaints/praise/whatever, send 'em to the address
John Dennis 38f226
# above.   -- 08/16/2001
John Dennis 38f226
John Dennis 38f226
John Dennis 38f226
# These are the variables you might want to tweak.
John Dennis 38f226
my $quota_attr = "mailQuota";
John Dennis 38f226
my $mail_attr = "mailRoutingAddress";
John Dennis 38f226
my $user = "cyrus";
John Dennis 38f226
my $passwd = "blah";
John Dennis 38f226
John Dennis 38f226
# These are the ones that you shouldn't have to.
John Dennis 38f226
my @entries = ();
John Dennis 38f226
my $index = 0;
John Dennis 38f226
my $counter = 0;
John Dennis 38f226
my $old_timestamp = 0;
John Dennis 38f226
my $timestamp = "199412161032Z";
John Dennis 38f226
John Dennis 38f226
# Open the /etc/cyrus_ldap_quota_time file; it's a long name, but
John Dennis 38f226
# shouldn't interfere with existing files :)  This file contains 1 line,
John Dennis 38f226
# the generalized time format of the last time the script ran.  This is
John Dennis 38f226
# used for the search, so we only update quotas that have been modified
John Dennis 38f226
# since then.
John Dennis 38f226
John Dennis 38f226
{
John Dennis 38f226
    if (-e "/etc/cyrus_ldap_quota_time")
John Dennis 38f226
    {
John Dennis 38f226
         open(TIME_FILE, "/etc/cyrus_ldap_quota_time") or die "could not
John Dennis 38f226
                              open the time file: $!\n";
John Dennis 38f226
     
John Dennis 38f226
         while(<TIME_FILE>) { $old_timestamp = $_; }
John Dennis 38f226
John Dennis 38f226
         close(TIME_FILE);
John Dennis 38f226
    }  
John Dennis 38f226
John Dennis 38f226
    # Now we deal with the case where the file doesn't exist, that is to
John Dennis 38f226
    # say the first time the script was run.
John Dennis 38f226
John Dennis 38f226
    unless ($old_timestamp == 0) { $timestamp = $old_timestamp; }
John Dennis 38f226
John Dennis 38f226
John Dennis 38f226
    # Now that we have that information, we can overwrite the file with
John Dennis 38f226
    # the new timestamp.  Maybe this overkill, but this is only a
John Dennis 38f226
    # temporary solution anyway.
John Dennis 38f226
John Dennis 38f226
    open(TIME_FILE, ">/etc/cyrus_ldap_quota_time") or die "could not
John Dennis 38f226
                              create file: $!\n";
John Dennis 38f226
John Dennis 38f226
    my @time = (localtime)[0..5];
John Dennis 38f226
John Dennis 38f226
    printf TIME_FILE $time[5] + 1900;
John Dennis 38f226
    printf TIME_FILE "%02d", $time[4] + 1;
John Dennis 38f226
    for (my $i = 3; $i >= 0; $i--) { printf TIME_FILE "%02d", $time[$i];}
John Dennis 38f226
    print TIME_FILE 'Z';
John Dennis 38f226
John Dennis 38f226
    close(TIME_FILE);
John Dennis 38f226
}
John Dennis 38f226
John Dennis 38f226
John Dennis 38f226
# This is where we do the search and then parse the results into a
John Dennis 38f226
# useable form.  In this case, an arry of hash entries.
John Dennis 38f226
{
John Dennis 38f226
    # Okay, this very ugly line sets up the LDAP search, and the strips
John Dennis 38f226
    # away the meaningless stuff.  This could be prettier, but I didn't 
John Dennis 38f226
    # want to add a dependency for an LDAP module, and everyone should
John Dennis 38f226
    # have LDAP search.  The greps are just to make things simpler.
John Dennis 38f226
John Dennis 38f226
    (my $query = "ldapsearch -x '(&(modifyTimestamp>=$timestamp)($quota_attr=*))' $quota_attr $mail_attr 
John Dennis 38f226
    | grep -v ^# | grep -v ^dn | grep -v ^version | grep -v ^search | grep -v ^result | grep -v ^\$") =~ s!\n!!;
John Dennis 38f226
John Dennis 38f226
    # Now actually do the commands in the above line.
John Dennis 38f226
    my $result = `$query`;
John Dennis 38f226
John Dennis 38f226
John Dennis 38f226
    # Split the output into an array, one entry per line.
John Dennis 38f226
    my @output = split(/\n/, $result);
John Dennis 38f226
John Dennis 38f226
    # Now go through each line . . .
John Dennis 38f226
    foreach (@output)
John Dennis 38f226
    {
John Dennis 38f226
         # Split on the attribute:value boundary.
John Dennis 38f226
         (my $key, my $value) = split(/: /);
John Dennis 38f226
John Dennis 38f226
         # Handle mailRoutingAddress; strip away everything after '@'.
John Dennis 38f226
         if ($value =~ m!@!)
John Dennis 38f226
         {
John Dennis 38f226
	     ($value, undef) = split (/@/, $value);
John Dennis 38f226
         }
John Dennis 38f226
John Dennis 38f226
         # Add each doctored up attribute:value pair to the entries array.
John Dennis 38f226
         $entries[$index]{$key} = $value;
John Dennis 38f226
John Dennis 38f226
         # A crude hack to make sure each of the two attributes makes it
John Dennis 38f226
         # into one of the entries array element.
John Dennis 38f226
         if ($counter % 2)
John Dennis 38f226
         {
John Dennis 38f226
  	     $index++;
John Dennis 38f226
         }
John Dennis 38f226
John Dennis 38f226
         $counter++;
John Dennis 38f226
    }
John Dennis 38f226
}
John Dennis 38f226
John Dennis 38f226
# Now here's the actual interaction with Cyrus IMAPd.  It's all pretty
John Dennis 38f226
# self-explanatory.
John Dennis 38f226
{
John Dennis 38f226
     my $imap = Cyrus::IMAP::Admin->new('localhost') or die "imap:
John Dennis 38f226
                         cannot connect to server: $!\n";
John Dennis 38f226
John Dennis 38f226
     $imap->send(undef, undef, "LOGIN %s %s", $user, $passwd) or die
John Dennis 38f226
                 "could not send user:pass to the server: $!\n";
John Dennis 38f226
John Dennis 38f226
     for (my $i = 0; $i <= $#entries; $i++)
John Dennis 38f226
     {
John Dennis 38f226
          $imap->setquota("user." . $entries[$i]{$mail_attr}, "STORAGE",
John Dennis 38f226
                          $entries[$i]{$quota_attr}) 
John Dennis 38f226
               or die "imap: could not set quota for
John Dennis 38f226
                            user.$entries[$i]{$mail_attr}: $!\n";
John Dennis 38f226
     }
John Dennis 38f226
John Dennis 38f226
     $imap=undef;
John Dennis 38f226
}