#!/usr/bin/perl -w
# This script (sophomorix-move) is maintained by Rüdiger Beck
# It is Free Software (License GPLv3)
# If you find errors, contact the author
# jeffbeck@web.de  or  jeffbeck@linuxmuster.net

# modules
use strict;
use Getopt::Long;
Getopt::Long::Configure ("bundling");
use Sophomorix::SophomorixConfig;
use Sophomorix::SophomorixBase;
use Net::LDAP;
use Sophomorix::SophomorixBase qw(
                                 print_line
                                 print_title
                                 time_stamp_AD
                                 time_stamp_file
                                 log_script_start
                                 log_script_end
                                 log_script_exit
                                 backup_auk_file
                                 check_options
                                 config_sophomorix_read
                                 );

use Sophomorix::SophomorixSambaAD qw(
                                 AD_user_move
                                 AD_bind_admin
                                 AD_dns_get
                                 AD_unbind_admin 
                                 AD_get_passwd
                                 AD_get_name_tokened
                                    );
my @arguments = @ARGV;

my $time_stamp_file=&time_stamp_file();
my $time_stamp_AD=&time_stamp_AD();
my $user_nummer=0;

my $alte_klasse;
my $neue_klasse;
my $login_versetzen;
my $old_status;
my $school_old;
my $school_new;
my $role_old;
my $role_new;

my $identifier;
my $alte_zeile="";
my $neue_zeile="";
my $new_home="";
my $new_homedir_above="";
my $old_home="";

my $altes_www="";
my $neues_www="";
my $www_link="";


my @users_for_quota=();

my $k;
my $v;
my $key;

my $move_file=${DevelConf::path_result}."/sophomorix.move";
my $move_file_new=${DevelConf::path_result}."/sophomorix.move.new";

# ===========================================================================
# Optionen verarbeiten
# ==========================================================================

# Variablen für Optionen
$Conf::log_level=1;
my $help=0;
my $info=0;
my $alt_gruppe="";
my $neu_gruppe="";
my $loginname="";
my $lock=0;
my $unlock=0;


# Parsen der Optionen
my $testopt=GetOptions(
           "verbose|v+" => \$Conf::log_level,
           "user|u=s" => \$loginname,
           "oldclass|o=s" => \$alt_gruppe,
           "newclass|n=s" => \$neu_gruppe,
           "lock" => \$lock,
           "unlock" => \$unlock,
           "info|i" => \$info,           
           "help|h" => \$help
          );

# Prüfen, ob Optionen erkannt wurden, sonst Abbruch
&check_options($testopt);

# Reading Configuration
my ($ldap,$root_dse) = &AD_bind_admin();
my $root_dns=&AD_dns_get($root_dse);
my %sophomorix_config=&config_sophomorix_read($ldap,$root_dse);
my ($smb_admin_pass)=&AD_get_passwd($DevelConf::sophomorix_file_admin,
                                     $DevelConf::secret_file_sophomorix_file_admin);

# --help
if ($help==1) {
   # Scriptname ermitteln
   my @list = split(/\//,$0);
   my $scriptname = pop @list;
   # Befehlsbeschreibung
   print('
sophomorix-move moves a user to a different AdminClass

Options
  -h  / --help
  -v  / --verbose
  -vv / --verbose --verbose
  -i  / --info
  -u user / --user user
  -o class / --oldclass class
  -n class / --newclass class
  --lock / --unlock

Please see the sophomorix-move(8) man pages for full documentation
');
   print "\n";
   exit;
}


# --loginname
if ($loginname ne "") {
  #
  print "Loginname $loginname angegeben.\n";
}


# --altgruppe
if ($alt_gruppe ne "") {
  #
  print "Alte Gruppe/Klasse $alt_gruppe angegeben.\n";
}


# --neugruppe
if ($neu_gruppe ne "") {
  #
  print "Neue Gruppe/Klasse $neu_gruppe angegeben.\n";
}


# --unlock
if ($unlock==1) {
    &unlock_sophomorix();
    exit;
}


# --lock
if ($lock==1) {
    &lock_sophomorix("lock",0,@arguments);
    exit;
}


# ===========================================================================
# Abbruch, wenn sophomorix.move fehlt oder leer
# ===========================================================================


# --info
if ($info==1) {
    my $count=0;
   if (not -e "$move_file"){
       print "$move_file does not exist!\n"; 
       print "Nothing to move: sophomorix.move does not exist!\n"; 
       exit;
   }
    open(USERVERSETZEN,"$move_file") 
            || die "ERROR: $!";
    print "\nThe following users can be moved:\n\n";
    printf "%-15s %-18s %-18s %-2s %-5s %-5s \n",
           "Login","OldClass","NewClass","S","Sold","Snew";
    &print_line;

    my @lines=();
    while(<USERVERSETZEN>){
       if(/^\#/){ # # am Anfang bedeutet Kommentarzeile
	   next;
       }
       push @lines, $_;
    }
    close(USERVERSETZEN);

    my @sorted_lines = sort {
        my @a_fields = split /::/, $a;
        my @b_fields = split /::/, $b;
 
        $a_fields[1] cmp $b_fields[1]  # string sort on 1st field, then
          ||
        $a_fields[0] cmp $b_fields[0]  # string sort on 2nd field
    } @lines;

    foreach my $line (@sorted_lines){
       chomp($line);
       $count++;
       ($login_versetzen,
        $alte_klasse,
        $neue_klasse,
        $old_status,
        $school_old,
        $school_new,
        $role_old,
        $role_new,
       )=split(/::/,$line);

    my $group_token_old=&AD_get_name_tokened($alte_klasse,$school_old,"adminclass");
    my $group_token_new=&AD_get_name_tokened($neue_klasse,$school_new,"adminclass");
    if (not defined $old_status){$old_status=""};
       # Ausgabe
       printf "%-16s%-19s%-19s%-3s%-6s%-6s\n",
              $login_versetzen,
              $group_token_old, 
              $group_token_new, 
              $old_status,
              $school_old,
              $school_new;
    }

    &print_line;
    print "$count users can be moved\n";
    &log_script_exit("",1,1,0,@arguments);
}




# ===========================================================================
# start
# ===========================================================================

&log_script_start(@arguments);

# repair.directories einlesen
#&get_alle_verzeichnis_rechte();

# fetch permission for all homes
#&fetch_repairhome();

# sophomorix database sichern
#&backup_user_database($time_stamp_file, "before-move.sql");

# sophomorix.move mitloggen
&backup_auk_file($time_stamp_file,"move","before",\%sophomorix_config);


# Datei mit den Schülern, die nicht versetzt wurden
open(NOCHVERSETZEN,">$move_file_new") 
     || die "ERROR: $!";

open(USERVERSETZEN,"$move_file") 
     || die "ERROR: $!";
while(<USERVERSETZEN>){
    if(/^\#/){ # # am Anfang bedeutet Kommentarzeile
        next;
    }
    chomp();
    $user_nummer++;
    ($login_versetzen, 
     $alte_klasse, 
     $neue_klasse,
     $old_status,
     $school_old,
     $school_new,
     $role_old,
     $role_new,
    )=split(/::/);
    if (not defined $old_status){$old_status=""};
   # Home ermitteln
   # altes home ermiteln
   #my ($old_home)=
   #    &Sophomorix::SophomorixPgLdap::fetchdata_from_account($login_versetzen);
   #my $home_share_dir=$old_home."/".$Language::share_dir;
   #my $home_task_dir=$old_home."/".$Language::task_dir;

   #if ($neue_klasse eq ${DevelConf::teacher}) {
   #   # in klasse lehrer versetzten
   #   $new_home="${DevelConf::homedir_teacher}/${login_versetzen}";
   #   $new_homedir_above="${DevelConf::homedir_teacher}";
   #} elsif ($neue_klasse eq "attic"){
   #   # move to attic
   #   $new_home="${DevelConf::attic}/${login_versetzen}";
   #   $new_homedir_above="${DevelConf::attic}";
   #} else {
   #   # in andere Klasse versetzten (ohne attic)
   #   $new_home="${DevelConf::homedir_pupil}/${neue_klasse}/${login_versetzen}";
   #   $new_homedir_above="${DevelConf::homedir_pupil}/${neue_klasse}";
   #} 

   # Abbruch, wenn nicht der richtige loginname versetzt wird
   if ($loginname ne "") {
     if ($login_versetzen ne $loginname) {
        print "##### $login_versetzen wird nicht versetzt\n";
        print NOCHVERSETZEN "$_\n";
        next;
     }
   }
   # Abbruch, wenn nicht aus der richtigen Alt-Klasse versetzt wird
   if ($alt_gruppe ne "") {
     if ($alte_klasse ne $alt_gruppe) {
        print "##### $login_versetzen wird NICHT aus $alt_gruppe versetzt!\n";
        print NOCHVERSETZEN "$_\n";
        next;
     }
   }
   # Abbruch, wenn nicht in die richtige Neu-Klasse versetzt wird
   if ($neu_gruppe ne "") {
     if ($neue_klasse ne $neu_gruppe) {
        print "##### $login_versetzen wird NICHT nach $neu_gruppe vesetzt!\n";
        print NOCHVERSETZEN "$_\n";
        next;
     }
   }

    my $group_token_old=&AD_get_name_tokened($alte_klasse,$school_old,"adminclass");
    my $group_token_new=&AD_get_name_tokened($neue_klasse,$school_new,"adminclass");
    &AD_user_move({ldap=>$ldap,
                   root_dse=>$root_dse,
                   root_dns=>$root_dns,
                   user=>$login_versetzen,
                   user_count=>$user_nummer,
                   group_old_basename=>$alte_klasse,
                   group_new_basename=>$neue_klasse,
                   group_old=>$group_token_old,
                   group_new=>$group_token_new,
                   school_old=>$school_old,
                   school_new=>$school_new,
                   role_old=>$role_old,
                   role_new=>$role_new,
                   creationdate=>$time_stamp_AD, 
                   smb_admin_pass=>$smb_admin_pass,
                   sophomorix_config=>\%sophomorix_config,
                  });

   # 0. rember login to set quota later
   #push @users_for_quota, $login_versetzen;

   ## die Daten aus dem Tausch-Verzeichnis dem Schüler in sein home moven
   #&save_tausch_klasse($login_versetzen, $alte_klasse);

   #if ($neue_klasse ne ${DevelConf::teacher}) {
   #  # first create sb entry, then create files (db_entry needed)
   #  &create_class_db_entry($neue_klasse);
   #  &provide_class_files($neue_klasse);
   #}

   ## removing bind mounts if necessary
   #if ($DevelConf::share_pointer_type eq "bind"){
   #    &delete_bind_sto_all_subdirs($home_share_dir);
   #    &delete_bind_to_all_subdirs($home_task_dir);
   #}

   # alte links/dirs entfernen
   #&remove_share_pointer($login_versetzen, $alte_klasse,$alte_klasse,"adminclass");
   #&remove_share_directory($login_versetzen, 
   #                        $alte_klasse,$alte_klasse,"adminclass");

   ## move home directory
   #&move_immutable_tree($old_home,$new_homedir_above);
   ## change primary group
   ## neue gruppe anlegen und gidnumber holen, falls erforderlich
   #my $gidnumber=&create_class_db_entry($neue_klasse);

   # ehemals testen
   #system("find $new_home -group $alte_klasse -print0 | xargs --no-run-if-empty -0 chown .$neue_klasse");

   ## links/dirs anlegen 
   #&create_share_link($login_versetzen, $neue_klasse,$neue_klasse,"adminclass");

   ## the following command must repair ALL dirs under $HOME
   ## because of chown -R .group $HOME above
   #&create_share_directory($login_versetzen, 
   #                        $neue_klasse,$neue_klasse,"adminclass");

   #&deleteuser_from_all_projects($login_versetzen,0);
   #&add_newuser_to_her_projects($login_versetzen,$neue_klasse);
   
   ## repair all binds if necessary
   ##&Sophomorix::SophomorixBase::repair_all_binds($login_versetzen);
}



close(USERVERSETZEN);
close(NOCHVERSETZEN);


# sophomorix.move mitloggen
&backup_auk_file($time_stamp_file,"move","after",\%sophomorix_config);



# ===========================================================================
# Nicht verarbeitete User nach sophomorix.move kopieren
# ===========================================================================
rename("$move_file_new","$move_file" );

# Setting Quota
#if ($Conf::use_quota eq "yes" 
#    and $user_nummer>0
#    and $user_nummer<101) {
#    my $users=join(",",@users_for_quota);
#    system("${DevelConf::executable_pfad}/sophomorix-quota --skiplock --users $users --noninteractive");
#    &nscd_stop();
#} elsif ($Conf::use_quota eq "yes" and $user_nummer>100){
#    system("${DevelConf::executable_pfad}/sophomorix-quota --skiplock --students --teachers --noninteractive");
#    &nscd_stop();
#} else {
#    if ($user_nummer==0){ 
#        &print_title("NOT setting quota (0 users moved)");
#    } else {
#        &print_title("NOT setting quota");
#    }
#}

# Creating Mailing Aliases and Lists
#if ($user_nummer>0) {
#    system("${DevelConf::executable_pfad}/sophomorix-mail --skiplock");
#    &nscd_stop();
#} else {
#    &print_title("NOT creating mailaliases/lists (0 users moved)");
#}


#&print_title("$user_nummer users moved");

&AD_unbind_admin($ldap);

&log_script_end(@arguments);
