#!/usr/bin/perl -w
# This script (sophomorix-exam-mode) 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 Quota;
use Getopt::Long;
Getopt::Long::Configure ("bundling");
use Sophomorix::SophomorixConfig;
use List::MoreUtils qw(uniq);
use String::Approx 'amatch';
use String::Approx 'adist';
use Net::LDAP;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Terse = 1; 
use JSON;
use File::Basename qw( basename
                       dirname
                     ); 
use Text::Iconv;
use Sophomorix::SophomorixBase qw(
                                 print_line
                                 print_title
                                 unlock_sophomorix
                                 lock_sophomorix
                                 log_script_start
                                 log_script_end
                                 log_script_exit
                                 backup_auk_file
                                 get_passwd_charlist
                                 get_plain_password
                                 check_options
                                 config_sophomorix_read
                                 result_sophomorix_init
                                 result_sophomorix_add
                                 result_sophomorix_check_exit
                                 result_sophomorix_print
                                 filelist_fetch
                                 remove_whitespace
                                 json_dump
                                 recode_utf8_to_ascii
                                 remove_from_list
                                 call_sophomorix_command
                                 );
use Sophomorix::SophomorixSambaAD qw(
                                 AD_get_unicodepwd
                                 AD_set_unicodepwd
                                 AD_school_create
                                 AD_bind_admin
                                 AD_unbind_admin
                                 AD_session_manage
                                 AD_user_set_exam_mode
                                 AD_user_unset_exam_mode
                                 AD_user_create
                                 AD_user_kill
                                 AD_group_create
                                 AD_group_addmember
                                 AD_group_update
                                 AD_get_schoolname
                                 AD_get_name_tokened
                                 AD_dn_fetch_multivalue
                                 AD_get_sessions
                                 AD_get_user
                                 AD_dns_get
                                 AD_object_search
                                 AD_examuser_create
                                 AD_examuser_kill
                                 AD_get_passwd
                                    );

my @arguments = @ARGV;

# option vars
$Conf::log_level=1;
my $help=0;
my $info=0;
my $json=0;

my $supervisor="";
my $participants="";
my $set_exam_mode=0;
my $unset_exam_mode=0;

my $subdir; # for collecting into
my $subdir_examuser=""; # for creating examusers and OU

# Parsen der Optionen
my $testopt=GetOptions(
           "help|h" => \$help,
           "info|i" => \$info,
           "json|j+" => \$json,
           "verbose|v+" => \$Conf::log_level,
#           "create|c" => \$create,
#           "kill" => \$kill,
#           "kill-all-sessions" => \$kill_all_sessions,
           "supervisor=s" => \$supervisor,
#           "session|s=s" => \$session,
#           "comment=s" => \$comment,
           "participants|m=s" => \$participants,
           "subdir=s" => \$subdir,
           "subdir-examuser=s" => \$subdir_examuser,
#           "add-participants=s" => \$add_participants,
#           "remove-participants=s" => \$remove_participants,
           "set-exam-mode|set" => \$set_exam_mode,
           "unset-exam-mode|unset" => \$unset_exam_mode,
#           "developer-session=s" => \$developer_session,
          );

my %sophomorix_result=&result_sophomorix_init("sophomorix-exam-mode");
# Prüfen, ob Optionen erkannt wurden, sonst Abbruch
&check_options($testopt,\%sophomorix_result,$json);

# Reading Configuration
my ($ldap,$root_dse) = &AD_bind_admin(\@arguments,\%sophomorix_result,$json);
my $root_dns=&AD_dns_get($root_dse);
my %sophomorix_config=&config_sophomorix_read($ldap,$root_dse,\%sophomorix_result);
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-exam-mode sets/unsets users in exam-mode

Options:
  -h  / --help
  -v  / --verbose
  -vv / --verbose --verbose
  -i  / --info

  sophomorix-exam-mode --set --supervisor <supi>  --participants <user1>,<user2>,...
  sophomorix-exam-mode --unset --subdir <subdir> <session> --participants <user1>,<user2>,...

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

# --info
if ($info==1) {
    # sophomorixExamMode other than ---
    my $filter="(&(objectClass=user)".
               "(sophomorixRole=examuser)".
               "(!(sophomorixExamMode=---)))";
    my $mesg = $ldap->search(
                      base   => $root_dse,
                      scope => 'sub',
                      filter => $filter,
                      attrs => ['sAMAccountName',
                                'sophomorixExamMode',
                     ]);

    my $max_user = $mesg->count;
    print "+--------------------+--------------------+\n";
    printf "|%-20s|%-20s|\n","participant","supervisor";
    print "+--------------------+--------------------+\n";
    for( my $index = 0 ; $index < $max_user ; $index++) {
        my $entry = $mesg->entry($index);
        my $sam=$entry->get_value('sAMAccountName');
        printf "|%-20s|%-20s|\n",$entry->get_value('sAMAccountName'),$entry->get_value('sophomorixExamMode');
    }
    print "+--------------------+--------------------+\n";
}


&result_sophomorix_check_exit(\%sophomorix_result,\%sophomorix_config,$json);
################################################################################
# Start
################################################################################
&log_script_start(\@arguments,\%sophomorix_result,\%sophomorix_config);



# --set-exam-mode
if ($set_exam_mode==1){
    if ($participants eq ""){
        print "\nERROR: you need to specify at least one participant\n\n";
        exit 88;
    }
    if ($supervisor eq ""){
        print "\nERROR: you need to specify the supervisor\n\n";
        exit 88;
    }

    my @participants=split(/,/,$participants);
    my $user_count=0;
    my $max_user_count=$#participants+1;
    foreach my $participant (@participants){
        $user_count++;
        my $ret=&AD_user_set_exam_mode({ldap=>$ldap,
                                root_dse=>$root_dse,
                                root_dns=>$root_dns,
                                supervisor=>$supervisor,
                                participant=>$participant,
                                user_count=>$user_count,
                                max_user_count=>$max_user_count,
                                json=>$json,
                                sophomorix_config=>\%sophomorix_config,
                                sophomorix_result=>\%sophomorix_result,
                            });

        if ($ret==0){
            # if <user> found and set in exammode, create <user>-exam
            &AD_examuser_create({ldap=>$ldap,
                                 root_dse=>$root_dse,
                                 root_dns=>$root_dns,
                                 participant=>$participant,
                                 subdir=>$subdir_examuser,
                                 user_count=>$user_count,
                                 max_user_count=>$max_user_count,
                                 smb_admin_pass=>$smb_admin_pass,
                                 json=>$json,
                                 sophomorix_config=>\%sophomorix_config,
                                 sophomorix_result=>\%sophomorix_result,
                               });

            if ($sophomorix_config{'INI'}{'EXAMMODE'}{'PASSWORDHASH_COPY'} eq "TRUE"){
                my $examuser=$participant.$sophomorix_config{'INI'}{'EXAMMODE'}{'USER_POSTFIX'};
                &print_title("Cloning password-hash of $participant to $examuser");
                my ($unicodepwd,$supplemental_credentials)= &AD_get_unicodepwd($participant,\%sophomorix_config);
                &AD_set_unicodepwd($examuser,$unicodepwd,$supplemental_credentials,\%sophomorix_config);
            }
        }
    }
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



# --unset-exam-mode
if ($unset_exam_mode==1){
    if ($participants eq ""){
        print "\nERROR: you need to specify at least one participant\n\n";
        exit 88;
    }

    my @participants=split(/,/,$participants);
    my $user_count=0;
    my $max_user_count=$#participants+1;
    foreach my $participant (@participants){
        if ($participant=~m/-exam$/){
            $participant=~s/-exam$//; 
        }
        $user_count++;
        # collect data
        if ($sophomorix_config{'INI'}{'EXAMMODE'}{'COLLECT_BEFORE_KILL'} eq "TRUE"){
            my $examuser=$participant.$sophomorix_config{'INI'}{'EXAMMODE'}{'USER_POSTFIX'};
            my $command;
            if (defined $subdir){
                $command="/usr/sbin/sophomorix-transfer --copy-account-data --collect-copy-exam ".$examuser." --subdir ".$subdir;
            } else {
                $command="/usr/sbin/sophomorix-transfer --copy-account-data --collect-copy-exam ".$examuser;

            }
            &call_sophomorix_command($Conf::log_level,$json,$command);
        }
        my $ret=&AD_user_unset_exam_mode({ldap=>$ldap,
                                          root_dse=>$root_dse,
                                          root_dns=>$root_dns,
                                          participant=>$participant,
                                          user_count=>$user_count,
                                          max_user_count=>$max_user_count,
                                          json=>$json,
                                          sophomorix_config=>\%sophomorix_config,
                                          sophomorix_result=>\%sophomorix_result,
                                        });
        if ($ret==0){
            &AD_examuser_kill({ldap=>$ldap,
                               root_dse=>$root_dse,
                               root_dns=>$root_dns,
                               participant=>$participant,
                               user_count=>$user_count,
                               max_user_count=>$max_user_count,
                               smb_admin_pass=>$smb_admin_pass,
                               json=>$json,
                               sophomorix_config=>\%sophomorix_config,
                               sophomorix_result=>\%sophomorix_result,
                             });
        }
    }
    &AD_unbind_admin($ldap);
    &log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);
}



################################################################################
# Sub
################################################################################
