#!/usr/local/bin/perl
#
# $Id: groupcreate,v 1.2 2003/05/30 22:43:44 visick Exp $
#
# groupcreate - add a group to LDAP 
#
# Copyright (C) 2002 Steven Barrus
# Copyright (C) 2002 Dana Dahlstrom
# Copyright (C) 2002 Robert Ricci
# Copyright (C) 2002 Spencer Visick
#
# See the AUTHORS file for contact info
#
# 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

use Getopt::Std;
use Term::ReadKey;
use Term::ReadLine;

require 'usertools.ph';

$term = new Term::ReadLine;

my @gids = ();
$lastgid = 1001;

$ldap = ldap_connect() || exit(1);

$objectclasses = [ 'posixGroup', 'top' ];
if ($config{group_objectclass}){
  for (split(/,/,$config{group_objectclass})){
    push(@$objectclasses,$_)
  }
}
@fields = ('cn', 'gidNumber', 'memberUid' );
if ($config{group_attribute}){
  for (split(/,/,$config{group_attribute})){
    push(@fields,$_)
  }
}

$interactive = 1;

%g = ();
while ($interactive) {

  if (&newgroup) {
    my $confirmation = &confirm;
    if ($confirmation == 1) {
      ldap_insert();
    } elsif ($confirmation == 2) {
      next;
    }
  }
  %g = ();
  $memberUids = "";
  $uid = "";

  print "Create another group? (y/N) ";
  last unless lc(<STDIN>) =~ /^y/;

}

sub confirm {
  if ($interactive) {
    &print_entry;
    do {
      print "Does this look okay? [(y)es,(n)o,(m)odify] ";
      $response = lc(<STDIN>);
      if ($response =~ /^y/) {
        return 1;
      } elsif ($response =~ /^n/) {
        return 0;
      } elsif ($response =~ /^m/) {
        return 2;
      }
    } while (1);
  } else {
    return 1;
  }
}

sub print_entry {
  my $value = "";
  print "**************************************************\n";
  foreach $field (@fields) {
    printf("%15s: ",$field);
    if ($field eq "memberUid"){
      $value = $memberUids;
    }else{
      $value = $g{$field};
    }
    if ($value) {
      print $value;
    } else {
      print "<blank>";
    }
    print "\n";
  }
  print "**************************************************\n";
}

sub newgroup {

  &get_gname;
  &get_gid;
  &get_memberuids;
  if($config{group_attribute}){
    for (@fields){
       if ($_ eq "owner"){
         &get_owner;
       }
       elsif (!($g{$_})){
         get_value($_);
       }
    }
   
  }

  return 1; 
}

sub get_gname {

  while ($interactive) {
    $g{cn} = $term->readline("Group name: ", $g{cn});
    $mesg = $ldap->search( base => $config{'groupbase'}, 
                           filter => "(cn=$g{cn})");
    if ($mesg->entry()){
      print "Sorry, $g{cn} already exists. Try another one.\n";
    } else {
      return;
    }
  }

}

sub get_gid {
  if (!@gids) {
    print "Getting list of GIDs - this could take several seconds\n";
    my $mesg = $ldap->search(base   => $config{'groupbase'},
                             filter => "(objectclass=posixGroup)",
                             attrs  => ["gidNumber"]);
    print $mesg->error if $mesg->code;
    @entry = $mesg->entries;
    for (@entry) {
      my $gid = $_->get_value("gidNumber");
      if ($gid) {
        $gids[$gid] = 1;
      }
    }
  }
  while (1) {
    if ($gids[$lastgid]) {
      $lastgid++;
    } else {
      if (($ldap->search(base => $config{'groupbase'},
                         filter => "gidNumber=$lastgid)"))->entry()) {
        $gids[$lastgid++] = 1;
      } else {
        $gids[$lastgid] = 1;
        $g{gidNumber} = $lastgid++;
        return;
      }
    }
  }
}

sub get_owner {

  while ($interactive) {
    $input = $term->readline("Group owner: ", $uid);

    if ($input eq "") {
      return;
    } elsif ($input =~ /uid=/) {
      $uid = (split ',', $')[0];
    } else {
      $uid = $input;
    }

    $mesg = $ldap->search(base => $config{'userbase'}, filter=> "(uid=$uid)");
    $owner = $mesg->entry();
    if ($owner) {
      $g{owner} = $owner->dn;
      return;
    } else {
      print "Sorry, $uid was not found in LDAP. Try another username.\n";
    }
  }

}

sub get_memberuids {

  while ($interactive) { 
    $memberUids = $term->readline("Members: ", $memberUids);
    $memberUids =~ s/,/ /g;
    $memberUids =~ s/\s+/, /g;
    @uids = split ', ', $memberUids;
    @bad_uids = ();
    @good_uids = ();

    foreach $uid (@uids) {
      if(($ldap->search(base=>$config{'userbase'},filter=>"(uid=$uid)"))->entry()){
        push @good_uids, $uid;
      } else {
        push @bad_uids, $uid;
      }
    }

    if (@bad_uids) {
      print "Sorry, the following usernames were not found in LDAP:\n";
      print join ", ", @bad_uids;
      print "\n";
    } else {
      $g{memberUid} = \@good_uids;
      return;
    }
  }

}

sub get_value{
  my $value = shift;
  $g{$value} = $term->readline("$value: ", $g{$value}); 
} 

sub ldap_insert {
  my $entry = Net::LDAP::Entry->new;
  $entry->dn( "cn=$g{cn},$config{'groupbase'}");
  $entry->add('objectclass' => $objectclasses);
  for (@fields){
    $entry->add("$_" => $g{$_});
  }
  $mesg = $entry->update( $ldap );
  print $mesg->error if $mesg->code;
  return $mesg->code;
}

__END__
=head1 NAME

groupcreate - add a group to LDAP

=head1 SYNOPSIS
     
groupcreate [-h]

=head1 DESCRIPTION

B<groupcreate> adds a group to the LDAP directory specified in
in /etc/usertools.conf or $HOME/.usertoolsrc. You will be prompted 
for a password with which to bind. You will be prompted for 
group name, members, and any other attributes in the list
group_attribute in the configuration file.

=head1 OPTIONS

B<-h>

Print out usage information.

=head1 BUGS

Lots probably, sorry. Contact AUTHORS if you find any.

=head1 AUTHORS

The usertools were written at the CADE by various opers. See the AUTHORS file 
for details.

=head1 SEE ALSO

groupmodify(1), groupsearch(1),
usercreate(1), userdelete(1), usermodify(1), userrevert(1), usersearch(1).

=cut 

