#
# Copyright (c) 2001 SuSE GmbH Nuernberg, Germany.  All rights reserved.
#
#
# $Id: create_user.pm,v 1.33 2003/12/17 09:09:38 varkoly Exp $
#
package create_user;
use strict;
use CGI qw(-no_xhtml);
use CGI::Carp qw(fatalsToBrowser);
use Storable qw(freeze thaw);
use Date::Calc qw(check_date);
use LDAPUtils;
use IMAPUtils;
use Net::LDAP;
use Digest::MD5;
use MIME::Base64;
use Display;
use Image::Magick;
use Utils;
use vars qw(@ISA);
use subs qw(exit);
# Select the correct exit function
*exit = $ENV{MOD_PERL} ? \&Apache::exit : sub { CORE::exit };
@ISA = qw(Display);


my $JavaScript=<<EOF;
function open_help_win( win_location ) {
    parem='width=540,height=500,directories=no,menubar=no,toolbar=no,resizable=yes';   contacts_window=window.open(win_location, 'ImapHelpWin', parem);
    if (!contacts_window.opener) contacts_window.opener=self;
}
function close_help_win() {
    document.all['ImapHelpWin'].close();
}
EOF


sub new {
    my $this = shift;
    my $self = new Display(@_);
   
# C SCHULSERVER
    $self->{'attr_short'} = ['uid', 'sn', 'givenname', 'birthday', 'userpassword','gidnumber', 'classe', 'alias', 'mail',
                         'preferredlanguage', 'admin' ];
    $self->{'attr_long'} =  ['uid', 'sn', 'givenname', 'birthday', 'userpassword','gidnumber', 'classe', 'alias', 'mail', 'vaddress', 'o', 'c',
                      'susetimezone', 'preferredlanguage', 'ou', 'title',
                      'initials', 'homephone',
                      'mobile', 'telephonenumber', 'facsimiletelephonenumber',
                      'pager', 'labeleduri', 'street', 'postalcode', 'l', 'st',
                      'jpegphoto', 'admin', 'rasAccess', 'religion' ];
# E SCHULSERVER
 
    return bless $self, $this;
}

sub display {
    my $this = shift;
    
    my $cgi = $this->{"cgi"};
    
    my $doit = $cgi->param('doit');

    if(defined $doit && $doit ne "") {
	$this->add_user();
    } else {
	$this->startup();
    }
}

sub startup {
    my $this = shift;

    my $q = $this->{"cgi"};
    my $session = $this->{"session"};
    my $confParam = $session->{"confParam"};
    my $message = ($session->getLanguage($confParam->{LANG},"EDIT_USER", "CREATE_USER"))->data();

    my $sessionID = $confParam->{"sessionID"};

    my $ADMINuid      = $confParam->{uid};
    my $ADMINpasswd   = $confParam->{passwd};
    
    my $ldapbase      = $confParam->{baseDN};
    my $ldaphost      = $confParam->{LDAPserver};
    my $ldapport      = $confParam->{LDAPport};
    my $imaphost      = $confParam->{IMAPserver}; 
    my $imapport      = $confParam->{IMAPport};
    my $params = {'userpassword' => "system",
		  'alias' => "checked",
		  'classe' => 'no' };
    my $cgi_params = ();
    my $read_from_session = $q->param('read_from_session');
    
    if( defined $read_from_session && $read_from_session == 1){
	$cgi_params = $this->session_to_form;
	#print STDERR "Read data from sesssion:\n";
	foreach my $key ( keys %$cgi_params){
	    #print STDERR "        $key: ".$cgi_params->{$key}."\n";
	}
    }else{
	$cgi_params = $q->Vars();
    }
    my $read_attrs = $this->{'attr_short'};
    if( $cgi_params->{'switch_attr'} || ($cgi_params->{'all_attrs'} && (! $cgi_params->{'less_attr'})) ){
	$read_attrs = $this->{'attr_long'};
    }
    
    my @must_attrs = ('sn', 'mail', 'givenname', 'birthday', 'o', 'c');
    my %must_attrs = ();
    foreach my $attr (@must_attrs){
	$must_attrs{$attr} = 1;
    }
    my $pre_mail   = $cgi_params->{'pre_mail'};
    my $mail       = $cgi_params->{'mail'};
    my $q_val      = $cgi_params->{'q_val'};
    my $tab        = $cgi_params->{'tab'};
    my $stab       = $cgi_params->{'stab'};
    my $filter     = $cgi_params->{'filter'};
   
    my @group = ();
    my %g_label = ();
# -- I SCHULSERVER    
    my @classes = ();
    my %class_label = ();
    my $user_fquota    = read_rcconfig("SCHOOL_FILE_QUOTA");
    my $teacher_fquota = read_rcconfig("SCHOOL_FILE_TEACHER_QUOTA");
    my $fq_val = $user_fquota;
# -- E SCHULSERVER    
    my @alias_arr = ();
    my $errs = "";
# -- C SCHULSERVER    
    my $user_mquota    = read_rcconfig("SCHOOL_MAIL_QUOTA");
    my $teacher_mquota = read_rcconfig("SCHOOL_MAIL_TEACHER_QUOTA");
    my $dflt_quota = $user_mquota;

    my $JavaQuota =<<EOF;
<script type="text/javascript">
    function setDefQuotas() {
        if ( document.form.gidnumber[0].selected  == true ) {
            window.document.form.q_val.value = $user_mquota;
            window.document.form.fq_val.value = $user_fquota;
	}
        if ( document.form.gidnumber[1].selected  == true ) {
            window.document.form.q_val.value = $teacher_mquota;
            window.document.form.fq_val.value = $teacher_fquota;
	}
        if ( document.form.gidnumber[2].selected  == true ) {
            window.document.form.q_val.value = $teacher_mquota;
            window.document.form.fq_val.value = $teacher_fquota;
	}
    }
</script>
EOF
# -- E SCHULSERVER    

# -- search for mail domains
    my $bind_dn = "uid=".$ADMINuid.",".$ldapbase;

    my $ldap = Net::LDAP->new("$ldaphost", port=>$ldapport, version => 3);
    if(!defined $ldap) {
        $this->display_error("can't contact LDAP Server",
                      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
        exit;
    }

    my $mesg = $ldap->bind (   # bind to a directory with dn and password
                            dn       => "$bind_dn",
                            password => "$ADMINpasswd"
                           );

    if($mesg->code != 0) {
        $errs = "bind $message->{failed}\n\n";
        $errs .= &LDAPerror($mesg);
        $this->display_error($errs,
                      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
        exit;
    }

# -- search for Domains

    $mesg = $ldap->search( base => "o=DNS,".$confParam->{baseDN},
                           scope => 'sub',
                           attrs => [ 'zoneName' ],
                           filter => "(&(relativeDomainName=@)(MTALocaldomain=true))" );
    if ($mesg->code != 0) {
        my $text = "search failed\n".&LDAPerror($mesg);
        $this->display_error($text,"$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
        $ldap->unbind;
        exit;
    }

    my @doms;
    push @doms, $confParam->{mailDomain};
    foreach my $i ($mesg->entries) {
        my @zones = $i->get_value('zoneName');
        foreach my $zn ( @zones ) {
            if( $zn !~ /IN-ADDR\.ARPA/i && $zn ne $confParam->{mailDomain} ) {
                push @doms, $zn;
            }
        }
    }
    @doms = sort(@doms);

# -- search for Groups
    
    $mesg = $ldap->search (  # perform a search
			   base   => "$ldapbase",
			   scope  => "one",
			   attrs => ['description', 'gidNumber','cn'],
			   filter => "(&(objectclass=posixgroup)(!(objectclass=SuSESchoolGroup))(!(objectclass=SuSESchoolClass)))"
			  );

# -- I SCHULSERVER	    
# -- E SCHULSERVER	    
    if($mesg->code == 0) {
	foreach my $entry ($mesg->all_entries) {
	    my $key  = $entry->get_value("gidNumber");
	    my $desc = $entry->get_value("description");
	    my $cn   = $entry->get_value("cn");
# -- C SCHULSERVER	    
	    if( $key == 103) {
		next;
	    } else {
  	      	 push @group, $key;
		 if( defined $desc && $desc ne '' ) {
  	            $g_label{$key} = $desc;
		 } else {
		    $g_label{$key} = $cn;
		 }
	    }
# -- E SCHULSERVER	    
	}
    } else {
	$errs = "search $message->{failed}\n\n";
	$errs .= &LDAPerror($mesg);
	$this->display_error($errs,
		      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
	exit;
    }
    $mesg = $ldap->search (  # perform a search
			   base   => "$ldapbase",
			   scope  => "one",
			   attrs => ['description', 'gidNumber','cn'],
			   filter => "objectclass=SuSESchoolClass"
			  );

    push @classes, 'all';
    $class_label{'all'} = 'all';
    if($mesg->code == 0) {
	foreach my $entry ($mesg->all_entries) {
	    my $key  = $entry->get_value("gidNumber");
	    my $cn   = $entry->get_value("cn");
  	    push @classes, $key;
	    $class_label{$key} = $cn;
	}
    }
# Wir sortieren die Klassen
   my @CLABS   = ();
   my %CLASVAL = ();
   foreach (@classes){
     push @CLABS, $class_label{$_};
     $CLASVAL{$class_label{$_}} = $_;  
   }
   @CLABS = sort classsort @CLABS;
   @classes = ();
   foreach (@CLABS) {
     push @classes, $CLASVAL{$_}; 
   }
# -------------------
    $mesg = $ldap->search (  # perform a search
			   base   => "$bind_dn",
			   scope  => "base",
			   attrs => ['c', 'o', 'maildomain'],
			   filter => "objectclass=*"
			  );

    if($mesg->code == 0) {
	 my $entry = $mesg->entry(0);
	 $params->{'preferredlanguage'} = $params->{'c'} = $entry->get_value("c");
	 $params->{'o'} = $entry->get_value('o');
    } else {
	$errs = "search $message->{failed}\n\n";
	$errs .= &LDAPerror($mesg);
	$this->display_error($errs,
		      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
	exit;
    }


    $ldap->unbind;   # take down session
    foreach my $attr (@{$read_attrs}){
	if( defined( $cgi_params->{$attr}) ){
	    $params->{$attr} = $cgi_params->{$attr};
	}
    }
    $params->{'birth_year'} = $cgi_params->{'birth_year'};
    $params->{'birth_month'} = $cgi_params->{'birth_month'};
    $params->{'birth_day'} = $cgi_params->{'birth_day'};

    
    my $langs;
    foreach my $l ( keys %$::lmsg ) {
	push @$langs, $l;
    }

    my @timezones = getTimeZones();

    my $html = "";
    $html .= $q->start_table({-class=>'AdminBorder', -cellspacing=>2, -cellpadding=>0, -width=>"100%"});
    $html .=	$q->start_Tr();
    $html .=	    $q->start_td();
#    $html .=		$q->start_multipart_form(
    $html .=		$q->start_form(
				-action => $confParam->{'cgi_path'}."/create_user.pl",
				-name => "form");
    $html .=		    $q->start_table({-border=>0, -cellspacing => 0, -cellpadding=>3, -width=>"100%"});
    $html .=			$q->start_Tr();
    $html .=			    $this->help_th(2, $message->{add_new_user}, "CREATE_USER");
    $html .=			$q->end_Tr();
    $html .=			$q->start_Tr();
    $html .=			    $q->td({-colspan => 2,  -height => "25", -align => "center"},
					   [$message->{star_fields}] );
    $html .=			$q->end_Tr();
    foreach my $attr ( @{$read_attrs} ){
	$html .=		$q->start_Tr();
	$html .=		    $q->start_td();
	if( $attr eq "alias" ){
	    $html .=			"";
	}else{
	    $html .=			$message->{$attr};
	    if( $must_attrs{$attr} ){
		$html .=			'*';
	    }
	}
	$html .=		    $q->end_td();
	$html .=		    $q->start_td();
	if($attr eq "c"){
	    $html .=			$q->textfield(-name=>"c",
                                                      -override=>0,
						      -size=>5,
						      -maxlength=>2,
						      -value=>$params->{$attr}).
					$q->a({-href=>"javascript:void(0);",
					       -onclick=>"$JavaScript; open_help_win('$confParam->{cgi_path}/country_codes.pl?sessionID=$sessionID')"},
					       $q->img({-border=>0,
							-src=>"$confParam->{image_path}/help1.gif",
							-width=>18,
							-height=>18,
							-alt=>"Help"
							})
					       );
	}elsif($attr eq "userpassword"){
	    $html .=                    $q->textfield(-name=>'passwd',
                                                      -default=>$params->{$attr},
                                                      -size=>20)."&nbsp;".
                                        $q->popup_menu(-name=>'pwmech',
                                                       -values=>["CRYPT","SMD5"]);
	}elsif($attr eq "mail"){
	    $html .=			'uid@'.
                                        $q->popup_menu(-name=>'mail',
                                                       -values=>\@doms,
                                                       -default=>$mail,
                                                       -width=>100);
	}elsif($attr eq "description"){
	    $html .=			$q->textarea(-name=>$attr,
						     -default=>$params->{$attr},
						     -rows=>4,
						     -columns=>30);
	}elsif($attr eq "preferredlanguage"){
	    $html .=			$q->popup_menu(-name=>'preferredlanguage',
                                                       -values=>$langs,
                                                       -default=>$params->{$attr},
                                                       -width=>160);
	}elsif($attr eq "gidnumber"){   
	    $html .= $JavaQuota;
	    $html .=			$q->popup_menu(-name=>'gidnumber',
                                                       -values=>\@group,
                                                       -labels=>\%g_label,
                                                       -default=>$params->{$attr},
						       -onChange=>"setDefQuotas()", 
                                                       -width=>160);
# -- I SCHULSERVER
	}elsif($attr eq "classe"){
	    $html .=			$q->scrolling_list(-name=>'classe',
                                                       -values=>\@classes,
                                                       -labels=>\%class_label,
                                                       -default=>$params->{$attr},
						       -size=>8,
		                                       -multiple=>'true',
                                                       -width=>160);
	}elsif( $attr eq "rasAccess" ){
	    $html .=			$q->checkbox(-name=>$attr,
						 -checked=>$params->{$attr},
						 -label=>""
						 );
	}elsif( $attr eq "admin" ){
	    $html .=			$q->checkbox(-name=>$attr,
						 -checked=>$params->{$attr},
						 -label=>""
						 );
        }elsif($attr eq "jpegphoto"){
            $html .=                    $q->img({-src => $confParam->{'cgi_path'}.
                                                         "/edit_user4admin.pl?displayphoto=1&uid=".
                                                         $params->{'uid'}."&sessionID=$sessionID",
                                                 -alt => $message->{'no_image_present'} }).$q->br();
            $html .=                $q->end_td();
            $html .=            $q->end_Tr();
            $html .=            $q->start_Tr();
            $html .=                $q->start_td();
            $html .=                $q->end_td();
            $html .=                $q->start_td();
            $html .=                    $q->filefield(-name=>$attr, -default => "");
        }elsif($attr eq "susetimezone"){
            if(! $params->{$attr}){
                my @dflt_timezone = parse_file("/etc/sysconfig/clock", "TIMEZONE=");
                $params->{$attr} = $dflt_timezone[0];
                $params->{$attr} =~ s/\"//g;
            }
            $html .=                    $q->popup_menu(-name=>"susetimezone",
                                                      -values => \@timezones,
                                                      -default => $params->{$attr},
                                                      -override=>0);
	}elsif($attr eq "birthday"){
            my $month = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12' ],
            my $days = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12',
                    '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24',
                    '25', '26', '27', '28', '29', '30', '31'];
            $html .=                    $message->{'year'}.": ".$q->textfield(-name =>"birth_year",
                                                      -size => 5,
                                                      -default => $params->{'birth_year'});
            $html .=                    " ".$message->{'month'}.": ".$q->popup_menu(-name=>"birth_month",
                                                      -values => $month,
                                                      -default => $params->{'birth_month'},
                                                      -override=>0);
            $html .=                    " ".$message->{'day'}.": ".$q->popup_menu(-name=>"birth_day",
                                                      -values => $days,
                                                      -default => $params->{'birth_day'},
                                                      -override=>0);
	}elsif( $attr eq "writeglobaladdress" ){
	    $html .=			$q->checkbox(-name=>$attr,
						 -checked=>$params->{$attr},
						 -label=>""
						 );
	}elsif( $attr eq "alias" ){
	    $html .=			$q->checkbox(-name=>$attr,
						 -checked=>$params->{$attr},
						 -label=>$message->{'default_alias'}
						 );
	    $html .=			"<BR><font size=2 color=FF3333>".$message->{'defalias_note'}."</font>";
	}else{
	    $html .=			$q->textfield(-name => $attr, -size => 30 , -default => $params->{$attr});
	}
	$html .=		    $q->end_td();
	$html .=		$q->end_Tr();
    }
    $html .=			$q->start_Tr();
    $html .=			    $q->start_td();
    $html .=				$message->{'quota'};
    $html .=			    $q->end_td();
    $html .=			    $q->start_td();
    $html .=				$q->textfield(-name => "q_val", -size => 15, -default => $dflt_quota);
    $html .=			    "MB".$q->end_td();
    $html .=			$q->end_Tr();
# - SCHULSERVER I
    $html .=			$q->start_Tr();
    $html .=			    $q->start_td();
    $html .=				$message->{'fquota'};
    $html .=			    $q->end_td();
    $html .=			    $q->start_td();
    $html .=				$q->textfield(-name => "fq_val", -size => 15, -default => $fq_val);
    $html .=			    "MB".$q->end_td();
    $html .=			$q->end_Tr();
# - SCHULSERVER C
    $html .=			$q->start_Tr();
    $html .=			    $q->start_td({ -align => "center"});
    if( $cgi_params->{'switch_attr'} || ($cgi_params->{'all_attrs'} && (! $cgi_params->{'less_attr'})) ){
	$html .=				$q->submit(-name=>"less_attr", -value=>$message->{"less_attr"});
	$html .=				$q->hidden(-name=>"all_attrs", -value => 1);
    }else{
        $html .=				$q->submit(-name=>"switch_attr", -value=>$message->{"more_attr"});
    }
    $html .=			    $q->end_td();
    $html .=			    $q->start_td({-align => "center"});
    $html .=				$q->submit(-name=>"doit", -value=>$message->{'add'});
    $html .=				$q->hidden(-name=>"sessionID", -value=>$sessionID);
    $html .=				$q->hidden(-name=>"filter", -value=>$filter);
    $html .=				$q->hidden(-name=>"filtered", -value=>1);
    $html .=				$q->hidden(-name=>"tab", -value=>$tab);
    # SCHULSERVER I
    if( ! $cgi_params->{'more_attr'} ) {
	 $html .= "\n".$q->hidden(-name=>"o", -value=>$params->{'o'});
	 $html .= "\n".$q->hidden(-name=>"c", -value=>$params->{'c'});
    }
    # SCHULSERVER E
    $html .=				$q->hidden(-name=>"stab", -value=>$stab);
    $html .=			    $q->end_td();
    $html .=			$q->end_Tr();
    $html .=		    $q->end_table();
    $html .=		$q->end_form();
    $html .=	    $q->end_td();
    $html .=	$q->end_Tr();
    $html .= $q->end_table();
			
    $this->back_url("$confParam->{cgi_path}/browse_user.pl?sessionID=$sessionID\&tab=$tab\&stab=$stab");
    $this->SUPER::display($html);
}

sub add_user {
    my $this = shift;

    my $q         = $this->{"cgi"};
    my $session   = $this->{"session"};
    my $confParam = $session->{"confParam"};
    my $sessionID = $confParam->{"sessionID"};
# -- I SCHULSERVER
    my @classes    = $q->param('classe');
    my $ldapbase      = $confParam->{baseDN};
    my $ldaphost      = $confParam->{LDAPserver};
    my $ldapport      = $confParam->{LDAPport};
    my $SORTED_HOME = read_rcconfig("SCHOOL_SORTED_HOME");
# -- E SCHULSERVER
    my $message   = ($session->getLanguage($confParam->{LANG},"CREATE_USER","EDIT_USER"))->data();

    my $tab        = $q->param('tab');
    my $stab       = $q->param('stab');
    
    if($this->form_to_session() ne "OK"){
	$this->display_error($message->{'write2session_failed'},
			     "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			     "\&tab=$tab\&stab=$stab");
	exit;
    };
    my $params = $q->Vars();
    my @def_folder = split(/ /,$message->{def_folder});
    my $errs="";
    if( $params->{"gidnumber"} == 100){
	$_ = $params->{"classe"};
	if( (/all/ || $#classes > 0) &&  $SORTED_HOME ne "no"  ) {
	   $this->display_error($message->{more_classes_for},
			     "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			     "\&tab=$tab\&stab=$stab&read_from_session=1");
	   exit;
	}
	if( $#classes < 0  && $SORTED_HOME ne "no"  ) {
	   $this->display_error($message->{no_classe_for},
			     "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			     "\&tab=$tab\&stab=$stab&read_from_session=1");
	   exit;
	}
	if(defined $params->{"admin"} && $params->{"admin"} eq "on") {
	   $this->display_error($message->{admin_for_kidd},
			     "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			     "\&tab=$tab\&stab=$stab&read_from_session=1");
	   exit;
	}
    } 
    my $bd;
    if( $params->{'birth_year'} !~ /^\d{4}$/ ){
print STDERR ":".$message->{year_four_digit}.":\n";
                $this->display_error($message->{year_four_digit},
                          "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
                          "\&tab=$tab\&stab=$stab\&read_from_session=1");
                exit;
    }elsif( ! check_date($params->{'birth_year'},$params->{'birth_month'},$params->{'birth_day'}) ){
                $this->display_error($message->{'invalid_birth_date'},
                          "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
                          "\&tab=$tab\&stab=$stab\&read_from_session=1");
                exit;
    }else{
#		$bd= $params->{'birth_year'}."-".$params->{'birth_month'}."-".$params->{'birth_day'};
#                $q->param(-name=>'birthday', -value=>"$bd");
		#$params->{'birthday'} = $params->{'birth_year'}."-".$params->{'birth_month'}."-".$params->{'birth_day'};
		$params->{'birthday'} = sprintf("%4d-%02d-%02d",$params->{'birth_year'},$params->{'birth_month'},$params->{'birth_day'});
    }
    
    if($params->{"uid"} eq "") {
       my $gn = to_ascii(lc($params->{"givenname"})); 
       $_ = to_ascii(lc($params->{"sn"}));
       my $SCHEME = read_rcconfig("SCHOOL_LOGIN_SCHEME");
       my $LOGIN_PREFIX = read_rcconfig("SCHOOL_LOGIN_PREFIX");
       my $n1 = substr($SCHEME,1,1); 
       my $n2 = substr($SCHEME,3,1); 
       if ( substr($SCHEME,0,1) eq "N" ) {
          $_ = substr($_,0,$n1).substr($gn,0,$n2);
       } else {
          $_ = substr($gn,0,$n1).substr($_,0,$n2);
       }
       # Mal schauen ob es diese uid schon gibt.
       my $NOOK = 1;
       my $uid=$LOGIN_PREFIX.$_;
       $uid =~ s/ //g;
       my $ldap = Net::LDAP->new("$ldaphost",port=>$ldapport,version=>3);
       if(!defined $ldap) {
   	 $this->display_error("can't contact LDAP Server",
   	     "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
   	 exit;
       }
       while ( $NOOK > 0 ) {
          my $mesg = $ldap->search( base => $ldapbase,
                      scope => "sub",
                      filter => "uid=$uid",
                      attrs => ["uidNumber"]);
 
          if( $mesg->count > 0 ) {
              $uid = $_.$NOOK; $NOOK++;
          } else {
                $NOOK = 0;
          }
      }       
      $q->param(-name=>'uid',-value=>"$uid");
    }
# -- E SCHULSERVER
    if($params->{"uid"} eq "" || $params->{"sn"} eq "" || $params->{"passwd"} eq "" || 
	    $params->{"mail"} eq "" || $params->{"o"} eq "" || $params->{"c"} eq "" ||
	    $params->{'givenname'} eq "" ) {

	$this->display_error($message->{miss_some_values},
			     "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			     "\&tab=$tab\&stab=$stab&read_from_session=1");
	exit;
	
    } else {
	
	if($params->{"uid"} =~ /[^a-zA-Z0-9-_]+/ ) {  #   Match a non-word character
	    #print STDERR "UID: ".$params->{"uid"}."\n";
	    $this->display_error($message->{'uid_invalid'}.$params->{"uid"}.":".$q->param('sn')." ".$q->param('givenname'),
				 "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
				 "\&tab=$tab\&stab=$stab&read_from_session=1");
	    exit;
	} 
	$params->{"uid"} = lc($params->{"uid"});  # uid always lowercase

	# Don't allow anybody or anyone as uid (these keywords are needed by cyrus for ACLs)
	if( ($params->{"uid"} eq "anyone") || ($params->{"uid"} eq "anybody")){ 
	    $this->display_error($message->{"value_anyone_not_allowed"},
				 "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
				 "\&tab=$tab\&stab=$stab&read_from_session=1");
	    exit;
	} 
	
	my $warn="";
#	if( (defined $params->{"alias"}) && ($params->{"givenname"} ne "" ) &&
#	    ( ($params->{"givenname"} =~ /[^a-zA-Z0-9-_]+/) || ($params->{"sn"} =~ /[^a-zA-Z0-9-_]+/) ) ){
#	    $warn = "\"".$params->{"givenname"}.".".$params->{"sn"}."\" ".$message->{'default_alias_not_set'};
#	    #print STDERR "WARN NO DEFALIAS\n";
#	    $params->{'alias'} = undef;
#	}

	if($params->{"mail"} !~ /\./) {
	    $this->display_error($message->{incorrect_mail_address},
			  "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			  "\&tab=$tab\&stab=$stab&read_from_session=1");
	    exit;
	}
	$params->{"mail"} = $params->{"uid"}."@".$params->{"mail"};
	
	if(length $params->{"passwd"} < 5 || ( $params->{"pwmech"} eq "SMD5" ? 0 : length($params->{"passwd"}) > 8 ) ) {
	    $this->display_error($message->{incorrect_passwd_length},
			  "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			  "\&tab=$tab\&stab=$stab&read_from_session=1");
	    exit;
	}

	if( $params->{"passwd"} !~ /^[:\/\w\d§\$\%&!]+$/ ) {
	    $this->display_error($message->{incorrect_passwd}.$params->{"passwd"},
			  "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			  "\&tab=$tab\&stab=$stab&read_from_session=1");
	    exit;
	}

	my $exit_value  = 0;
	my $text = "";
        $text .= "New uid: <b>".$q->param('uid')."</b>\n";
	if($warn ne ""){
	    $text .= $warn."\n\n";
	}
	($exit_value, $errs) = $this->to_ldap();
	if($exit_value != 0) {
	    $text .= "add_user_ldap $message->{failed}\n\n";
	    $this->display_error($text.$errs,
			  "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			  "\&tab=$tab\&stab=$stab&read_from_session=1");
	    exit;
	}	
   	$text .= $errs; 
	$text .= "add_user_ldap $message->{success}\n";

	($exit_value, $errs) = $this->to_cyrus(@def_folder);
	if($exit_value != 0) {
	    $text .= "add_user_cyrus $message->{failed}\n\n";
	    $this->revoke("imap");
	    $this->revoke("ldap");
	    $this->display_error($text.$errs."\n$message->{revoke_action}",
			  "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID".
			  "\&tab=$tab\&stab=$stab&read_from_session=1");
	    exit;
	}	
	$text .= "add_user_cyrus $message->{success}\nset_quota $message->{success}\n";
# SCHULSERVER I
# Eintragen ins AddresBook
# Setting file system quota
	my $uid=$q->param('uid');
        my $fq_val     = $q->param('fq_val');
        if(defined $fq_val && (!($fq_val =~ /[^\d]+/)) && $fq_val ne '') {
                $session->suad_setfquota('/home',$uid,$fq_val);
        }
        $q->delete('fq_val');
# SCHULSERVER E
	
	$q->delete('uid');
	$q->delete('sn');
	$q->delete('givenname');
	$q->param(-name=>'passwd', -value=>"system");
	$q->delete('mail');
	$q->delete('o');
	$q->delete('l');
	$q->delete('c');
	$q->delete('d');
	$q->delete('m');
	$q->delete('y');
	$q->delete('aliases');
	$q->delete('q_val');
#	$q->delete('writeglobaladdress');
	
	$this->display_msg($text,
			   "$confParam->{cgi_path}/create_user.pl?sessionID=$sessionID\&tab=$tab\&stab=$stab",1000);
	$this->cleanupsession();
    }
}

sub to_ldap  () {
    my $this = shift;
    my @attrnames = ( "gidnumber", "uid", "sn", "givenname","birthday",
		      "mail", "o", "l", "c", "preferredlanguage", "title",
		      "initials", "homephone", "mobile", "facsimiletelephonenumber", "pager", 
		      "telephonenumber", "labeleduri", "street", "postalcode", "st");

    my $q         = $this->{"cgi"};
    my $session = $this->{"session"};
    my $confParam = $session->{"confParam"};
    my $passwd     = $q->param('passwd');
    my $params	   = $q->Vars();
    my $defalias   = $q->param('alias');
    my $lang       = $q->param('language');
    my $group      = $q->param('group');
    my $uid        = $q->param('uid');
    my $pwmech     = $q->param('pwmech');
# -- I SCHULSERVER
    my $no_extern   = read_rcconfig("SCHOOL_NO_EXTERN_MAIL");
    my $SORTED_HOME = read_rcconfig("SCHOOL_SORTED_HOME");
    my $groupware   = read_rcconfig("SCHOOL_GROUPWARE") || 'all';
    my @classes    = $q->param('classe');
    my $alias_errs = "";
    my $mailenabled = "OK";
# -- C SCHULSERVER
 
    my $ADMINuid      = $confParam->{uid};
    my $ADMINpasswd   = $confParam->{passwd};
    my $ldapbase      = $confParam->{baseDN};
    my $ldaphost      = $confParam->{LDAPserver};
    my $ldapport      = $confParam->{LDAPport};
    my $sessionID     = $confParam->{"sessionID"};
    my $message   = ($session->getLanguage($confParam->{LANG},"CREATE_USER"))->data();
    my $errs = "";
    my $command = $confParam->{bin_path}."/add_user_ldap -";

    my $cmd_args = "H=$ldaphost\nP=$ldapport\nal=$ADMINuid\n";
    $cmd_args.= "bDN=$ldapbase\nap=$ADMINpasswd\n";

# -- I SCHULSERVER
    my $cn = "";
    my $homedir = "/tmp";
    my $gidnumber  = $q->param('gidnumber');

    # Einstellung der Rechte auf die eigene Angaben
    my $teacheraci = "cn initials mail title l description street postalcode st c homephone mobile pager facsimiletelephonenumber telephonenumber labeleduri sn givenname preferredLanguage birthday jpegphoto";
    my $childaci   = "preferredLanguage";

    # Verbindung zum Ldap-Server aufbauen
    my $bind_dn = "uid=".$ADMINuid.",".$ldapbase;
    my $ldap = Net::LDAP->new("$ldaphost",port=>$ldapport,version=>3);
    if(!defined $ldap) {
	$this->display_error("can't contact LDAP Server",
		      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
	exit;
    }

    my $mesg = $ldap->bind (   # bind to a directory with dn and password
			    dn       => "$bind_dn",
			    password => "$ADMINpasswd"
			   );

    if($mesg->code != 0) {
	$errs = "bind $message->{failed}\n\n";
	$errs .= &LDAPerror($mesg);
	$this->display_error($errs,
		      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
	exit;
    }
    $errs = $alias_errs;
    my $ou="";
    my $classescn = "";
    if( $params->{"classe"} =~ /all/) {
	@classes = ();
        $mesg = $ldap->search (  # perform a search
                           base   => "$ldapbase",
                           scope  => "sub",
                           attrs => ['cn','gidnumber'],
                           filter => "objectclass=SuSESchoolClass"
                       );
	if($mesg->code == 0) {
          foreach my $entry ($mesg->all_entries) {
             my $cn = $entry->get_value("cn");
             my $gn = $entry->get_value("gidnumber");
	     push @classes,   $gn;
	     $classescn .= "$cn ";
	     $cmd_args .= "class=$cn\n";
	  }
	  $ou .= "all ";
	} else {
             $errs .= "search $message->{failed}\n\n";
             $errs .= &LDAPerror($mesg);
             $ldap->unbind;   # take down session
             $this->display_error($errs,
                      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
             exit;
	}    
    } else {
       foreach my $i (@classes) {
         $mesg = $ldap->search (  # perform a search
                           base   => "$ldapbase",
                           scope  => "sub",
                           attrs => ['cn'],
                           filter => "(&(objectclass=posixgroup)(gidnumber=$i))"
                       );
	 $cn = $mesg->entry(0)->get_value("cn");
	 $cmd_args .= "class=$cn\n";
	 $ou .= "$cn ";
	 $classescn .= "$cn ";
       }
    }
    chop $classescn;
    $q->param(-name=>'classescn',-value=>$classescn);
    chop $ou;
    if( $ou ne "" ) {
        $cmd_args .= "ou=$ou\n";
    }
    # Einstellung der Rechte auf die eigene Angaben
    if( $gidnumber == 102 ) {
        $mesg = $ldap->modify ( "cn=users,$ldapbase", add => { memberUid => "$uid" } );
        $mesg = $ldap->modify ( "cn=workstations,$ldapbase", add => { memberUid => "$uid" } );
	$mesg = $ldap->modify($bind_dn, replace => {"defaultUserAci" => $teacheraci});
	$homedir = "/home/teachers/$uid";
	$cmd_args.= "description=$message->{teacher}\n";
	my $admin = $params->{"admin"};
        if(defined $params->{"admin"} && $params->{"admin"} eq "on") {
          $mesg = $ldap->modify ( "cn=Admins,$ldapbase", add => { member => "uid=$uid,$ldapbase" } );
	    if($mesg->code != 0) {
		$errs .= "modify $message->{failed}\n\n";
		$errs .= &LDAPerror($mesg);
		$this->display_error($errs,
			      "$confParam->{cgi_path}/menu.pl?sessionID=$sessionID");
		exit;
	    }
	}
    } elsif($gidnumber == 100) {
	if( $SORTED_HOME ne "no" ) {
		$homedir = "/home/$cn/$uid";
	} else {
		$homedir = "/home/users/$uid";
	}
	if ( $no_extern eq "yes" ) { $mailenabled = "local_only"; }
	$mesg = $ldap->modify($bind_dn, replace => {"defaultUserAci" => $childaci});
	$cmd_args.= "description=$message->{kidd}\n";
    } else {
	$mesg = $ldap->search (  # perform a search
                           base   => "$ldapbase",
                           scope  => "sub",
                           attrs => ['cn','description'],
			   filter => "(&(objectclass=posixgroup)(gidnumber=$gidnumber))"
			);
	$cn 	        = $mesg->entry(0)->get_value("cn");
	my $description = $mesg->entry(0)->get_value("description");
	$homedir = "/home/$cn/$uid";
	$mesg = $ldap->modify($bind_dn, replace => {"defaultUserAci" => $teacheraci});
	if(defined $message->{$description} && $message->{$description} ne '' ) {
		$description = $message->{$description};
	}
	if($description ne '') {
		$cmd_args.= "description=$description\n";
	}
    }
# -- E SCHULSERVER

    my $crypt_passwd = "*";
    if( $pwmech eq "CRYPT" ) {
	my $salt =  pack("C2",(int(rand 26)+65),(int(rand 26)+65));
	$crypt_passwd = crypt $passwd,$salt;
	$crypt_passwd = "{crypt}".$crypt_passwd;
    } elsif( $pwmech eq "SMD5" ) {
	my $salt =  pack("C5",(int(rand 26)+65),(int(rand 26)+65));
	my $ctx = new Digest::MD5();
	$ctx->add($passwd);
	$ctx->add($salt);
	$crypt_passwd = "{smd5}".encode_base64($ctx->digest.$salt, "");
    }
    $cmd_args.= "up=$crypt_passwd\n"; 
    
    foreach my $attr (@attrnames){
	if( defined $params->{$attr} && ($params->{$attr} ne "") ){
	      $cmd_args .= "$attr=".$params->{$attr}."\n";
	}
    }
    
    if( (defined $params->{"alias"}) && ($params->{"givenname"} ne "" ) ){
	my $tmp_alias;
	if ( $confParam->{LANG} eq "HU" ) {
	  $tmp_alias = to_ascii($params->{"sn"}).".".to_ascii($params->{"givenname"});
	} else {
	  $tmp_alias = to_ascii($params->{"givenname"}).".".to_ascii($params->{"sn"});
	}
	$tmp_alias =~ s/ /./g;
	$mesg = $ldap->search (  # perform a search
                           base   => "$ldapbase",
                           scope  => "sub",
                           attrs => ['alias'],
                           filter => "alias=$tmp_alias"
                       );
	if ( $mesg->count > 0 ) { 
	   $alias_errs .= $message->{alias_exist}.": $tmp_alias \n";
	} else {
	   $cmd_args .= "alias=".$tmp_alias."\n";
	}
    } 
    if( defined $params->{"description"} ){
	$params->{"description"} =~ s/(\r?\n)/$1 /mg;
	$cmd_args .= "description=".$params->{"description"}."\n";
    }
    if(defined $params->{"writeglobaladdress"} && $params->{"writeglobaladdress"} eq "on") {
	$cmd_args .= "writeglobaladdress=allowed\n";
    } else {
	$cmd_args .= "writeglobaladdress=denied\n";
    }
# -- I SCHULSERVER

    $cmd_args .= "mailenabled=$mailenabled\n";
    $cmd_args .= "homedirectory=$homedir\n";
    $cmd_args .= "groupware=$groupware\n";
    if(defined $params->{"rasAccess"} && $params->{"rasAccess"} eq "on") {
	$cmd_args .= "rasaccess=1\n";
    } else {
	$cmd_args .= "rasaccess=0\n";
    }
# -- I SCHULSERVER
# print STDERR "$cmd_args\n";
    $errs .= cmd_pipe("$command", "$cmd_args");
    if($errs ne "") {
        return (-1, $errs);
    }

# -- I SCHULSERVER
    # Was ist die neue uidNumber ??
    $mesg = $ldap->search( base => $ldapbase,
                           scope => "sub",
                           filter => "uid=$uid",
                           attrs => ["uidNumber"]);
 
    my $uidNumber = "-1";
    if($mesg->code == 0){
        $uidNumber = $mesg->entry(0)->get_value("uidNumber");
	$q->param(-name=>'uidnumber',-value=>"$uidNumber");
	if($groupware eq 'all' || $groupware eq 'phpgw' ){
		my $mysqlc = "mysql -u $ADMINuid -p\'$ADMINpasswd\' -h mailserver phpgroupware";
		my $mysqla = " INSERT INTO phpgw_preferences VALUES (\'$uidNumber\',\'$message->{phpgw_prefs}\')";
		system("echo -E \"$mysqla\" | $mysqlc");
	}
    }
    $mesg = $session->suad_smbadduser($uid, $passwd);
    if( $mesg->code() ne "OK" ){
       $errs .= "smb_adduser ".$message->{'failed'}.": ".$mesg->code()."\n";
    }else{
       $errs .= "smb_adduser ".$message->{'success'}."\n";
    }
    $mesg = $session->suad_mkdir($homedir, '711');
    if( $mesg->code() ne "OK" ){
       $errs .= "create_homedir ".$message->{'failed'}.": ".$mesg->code()."\n";
    }else{
       $errs .= "create_homedir ".$message->{'success'}."\n";
    }
    $mesg = $session->suad_copydir('/etc/skel/', $homedir);
    if( $mesg->code() ne "OK" ){
       $errs .= "prepare_homedir ".$message->{'failed'}.": ".$mesg->code()."\n";
    }else{
       $errs .= "prepare_homedir ".$message->{'success'}."\n";
    }
    $mesg = $session->suad_chown($homedir,$uidNumber,$gidnumber);
    if( $mesg->code() ne "OK" ){
       $errs .= "prepare_homedir2 ".$message->{'failed'}.": ".$mesg->code()."\n";
    }else{
       $errs .= "prepare_homedir2 ".$message->{'success'}."\n";
    }
    $mesg = $session->suad_move("$homedir/.profiles","/home/profile/$uid");
    if( $mesg->code() ne "OK" ){
       $errs .= "prepare_homedir3 ".$message->{'failed'}.": ".$mesg->code()."\n";
    }else{
       $errs .= "prepare_homedir3 ".$message->{'success'}."\n";
    }
    $mesg = $session->suad_chown($homedir.'/public_html',$uidNumber,'nogroup');
    $mesg = $session->suad_chmod($homedir.'/public_html','2755');
    #make some symlinks to make the life easier
    $session->suad_stdout_exec("ln -s /home/all      $homedir/+all");
    $session->suad_stdout_exec("ln -s /home/groups   $homedir/+groups");
    $session->suad_stdout_exec("ln -s /home/software $homedir/+software");
    if($gidnumber == 102){
    	$session->suad_stdout_exec("ln -s /home/groups/teachers   $homedir/+allteachers");
    } elsif ($gidnumber != 100) {
    	$session->suad_stdout_exec("ln -s /home/groups/$cn   $homedir/+all$cn");
    }
# -- E SCHULSERVER
    return (0, $errs);
}

sub to_cyrus (){
    my $this = shift;
    my @def_folder = @_;
    my $q         = $this->{"cgi"};
    my $confParam = $this->{"session"}->{"confParam"};

    my $ADMINuid      = $confParam->{uid};
    my $ADMINpasswd   = $confParam->{passwd};
    my $imaphost      = $confParam->{IMAPserver}; 
    my $imapport      = $confParam->{IMAPport};

    my $uid        = $q->param('uid');
    my $gidnumber  = $q->param('gidnumber');
    my $q_val      = $q->param('q_val') * 1024;
    my $classescn  = $q->param('classescn');

    my $errs = "";
    my $command = $confParam->{bin_path}."/add_user_cyrus -";

       $uid = lc($uid);  # uid always lowercase
    my $cmd_args  = "H=$imaphost\nP=$imapport\nal=$ADMINuid\n";
       $cmd_args .= "ap=$ADMINpasswd\nuid=$uid\n";

    if(defined $q_val && $q_val ne "") {
	$cmd_args .= "qv=$q_val\n";
    }
    foreach(@def_folder){
	$cmd_args .= "mb=$_\n";
    }

    $errs = cmd_pipe($command, $cmd_args);
# -- I SCHULSERVER
# teachers & administratoren haben alle Rechte fuer klassenmailboxen
    if ( $gidnumber == 102 || $gidnumber == 104) {
      my $imap = new Net::IMAP($imaphost, Debug => 0) or die ("can't connect to $imaphost: $!\n");
      my $resp = $imap->login($ADMINuid, $ADMINpasswd);
      if($$resp{Status} ne "ok") {
         $errs .= "IMAP login failed: Serverresponse: $$resp{Status} => $$resp{Text}\n";
      } else {
	foreach(split / /, $classescn){
	    $resp = $imap->setacl($_,$uid,"lrswipcd");
	    if($$resp{Status} ne "ok") { 
	      $errs .= "IMAP setacl failed for $uid:  Serverresponse: $$resp{Status} => $$resp{Text}\n";
	    }
	}
      }
      $imap->logout;
    }
# -- E SCHULSERVER
    if($errs ne "") {
        return (-1, $errs);
    }
    return (0, $errs);
}

sub default_folder(@) {
    my $this = shift;

    my $q         = $this->{"cgi"};
    my $confParam = $this->{"session"}->{"confParam"};

    my $ADMINuid      = $confParam->{uid};
    my $imaphost      = $confParam->{IMAPserver}; 
    my $imapport      = $confParam->{IMAPport};

    my $uid        = $q->param('uid');
    my $passwd     = $q->param('passwd');

    my @folder = @_;

	$uid = lc($uid);  # uid always lowercase
    my $errs    = "";
    my $command = $confParam->{bin_path}."/add_folder -";
    my $cmd_args  = "H=$imaphost\nP=$imapport\nal=$ADMINuid\n";
       $cmd_args .= "ul=$uid\nup=$passwd\n";

    foreach (@folder) {
	$cmd_args .= "mb=$_\n";
    }

    $errs = cmd_pipe($command, $cmd_args);
    if($errs ne "") {
        return (-1, $errs);
    }
    return (0, $errs);
}

sub revoke {
    my $this = shift;
    my $todo = shift;

    my $q         = $this->{"cgi"};
    my $confParam = $this->{"session"}->{"confParam"};

    my $ADMINuid      = $confParam->{uid};
    my $ADMINpasswd   = $confParam->{passwd};
    
    my $ldapbase      = $confParam->{baseDN};
    my $ldaphost      = $confParam->{LDAPserver};
    my $ldapport      = $confParam->{LDAPport};
    my $imaphost      = $confParam->{IMAPserver}; 
    my $imapport      = $confParam->{IMAPport};

    my $uid        = $q->param('uid');
	$uid = lc($uid);  # uid always lowercase

    my $ev = 0;
    my $errs = "";
    my $command = "";

    if($todo eq "imap") {

	$command = $confParam->{bin_path}."/del_user -";
        my $cmd_args  = "CH=$imaphost\nCP=$imapport\n";
	$cmd_args    .= "al=$ADMINuid\nap=$ADMINpasswd\nuid=$uid\nimap\n";

        $errs = cmd_pipe($command, $cmd_args);
	
    } elsif ($todo eq "ldap") {

	$command = $confParam->{bin_path}."/del_user -";
        my $cmd_args  = "LH=$ldaphost\nLP=$ldapport\n";
	   $cmd_args .= "al=$ADMINuid\nap=$ADMINpasswd\n";
	   $cmd_args .= "uid=$uid\nldap\nbDN=$ldapbase\n";
	
    	$errs = cmd_pipe($command, $cmd_args);
    }    

    if($errs ne "") {
        return (-1, $errs);
    }
    return (0, $errs);
}

sub form_to_session{
    my $this = shift;
    my $session = $this->{"session"};
    my $cgi = $this->{'cgi'};

    my %cgi_params = $cgi->Vars();
    
    my $frozen = freeze (\%cgi_params);
    $frozen = unpack('H*',$frozen);

    my %tmp = ( "formdata" => $frozen );
    my $s_reply=$session->modify(\%tmp);
    if( $s_reply->code() ne "OK" ) {
	return "ERR"
    }else {
	return "OK";
    }

}

sub session_to_form{
    my $this = shift;
    my $session = $this->{"session"};
    my $confParam = $session->{'confParam'};

    my $frozen = $confParam->{'formdata'};
    $frozen = pack('H*',$frozen);
    my $formdata = thaw($frozen);
    return $formdata;
}

sub cleanupsession{
    my $this = shift;
    my $session = $this->{"session"};
    my $reply = $session->modify({"formdata" => "" });
}

sub classsort($$) {
    my $a = shift;
    my $b = shift;

    $a =~ /(\d+)/;
    my $A = chr(64 + $1);
    $a =~ s/(\d+)/$A/;

    $b =~ /(\d+)/;
    my $B = chr(64 + $1);
    $b =~ s/(\d+)/$B/;

    return $a cmp $b;
    
}

1;
