#!/usr/bin/perl -w
# This script (sophomorix-school) 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 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
                                 mount_school
                                 umount_school
                                 testmount_school
                                 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
                                 );
use Sophomorix::SophomorixSambaAD qw(
                                 AD_school_create
                                 AD_bind_admin
                                 AD_unbind_admin
                                 AD_user_create
                                 AD_group_create
                                 AD_group_addmember
                                 AD_group_update
                                 AD_get_schoolname
                                 AD_get_name_tokened
                                 AD_dn_fetch_multivalue
                                 AD_get_shares_v
                                 AD_dns_get
                                 AD_get_passwd
                                 AD_object_search
                                 AD_gpo_listall
                                 AD_gpo_create
                                 AD_gpo_kill
                                 AD_gpo_dump
                                    );

my @arguments = @ARGV;

my $lock=0;
my $unlock=0;

my $school="";
my $create=0;
my $create_all_schools=0;
my $kill=0;

my $gpo_listall=0;
my $gpo_create="";
my $gpo_kill="";
my $gpo_dump="";
my $gpo_dump_type="";
my $gpo_dump_path="";

my $mount="";
my $umount="";
my $listmount=0;

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

# Parsen der Optionen
my $testopt=GetOptions(
           "help|h" => \$help,
           "info|i" => \$info,
           "json|j+" => \$json,
           "verbose|v+" => \$Conf::log_level,
           "create|c" => \$create,
           "create-all-schools" => \$create_all_schools,
           "kill" => \$kill,
           "school=s" => \$school,
           "mount=s" => \$mount,
           "umount=s" => \$umount,
           "listmount|list-mount" => \$listmount,
           "gpo-listall" => \$gpo_listall,
           "gpo-create=s" => \$gpo_create,
           "gpo-kill=s" => \$gpo_kill,
           "gpo-dump=s" => \$gpo_dump,
           "gpo-dump-type=s" => \$gpo_dump_type,
           "gpo-dump-path=s" => \$gpo_dump_path,
          );

my %sophomorix_result=&result_sophomorix_init("sophomorix-school");
# 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-school lists,adds and removes schools


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

  --school <schoolname>
  --create --school <schoolname>
  --kill --school <schoolname>

  --create-all-schools   (creates all configured schools from sophomorix.conf)

  --mount <school>
  --umount <school>
  --listmount

  --gpo-create <school>
    creates/updates sophomorix:school:<school> gpo
  --gpo-kill <school>
    kills sophomorix:school:<school> gpo
  --gpo-listall
  --gpo-listall -j (return parsed data as JSON)
Export a gpo:
  --gpo-dump {...} --gpo-dump-type <school, ...> --gpo-dump-path /path/to/dump


Dumping data:                     
  -ij / --info --json              (dump configuration)
  -j / --json                      (dump as a nice json object)
  -jj / --json --json              (dump as a compact json object)
  -jjj / --json --json --json      (dump as a perl hash)


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


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


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


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


# ============================================================
# listing schools
# ============================================================
# --info
if ($info==1){
    my $ref_share_v=&AD_get_shares_v({ldap=>$ldap,
                                       root_dse=>$root_dse,
                                       root_dns=>$root_dns,
                                       smb_admin_pass=>$smb_admin_pass,
                                       sophomorix_config=>\%sophomorix_config,
                                     });
    my $jsoninfo="SHARES";
    my $jsoncomment="All Shares";
    &json_dump({json => $json,
                jsoninfo => $jsoninfo,
                jsoncomment => $jsoncomment,
                log_level => $Conf::log_level,
                hash_ref => $ref_share_v,
                sophomorix_config => \%sophomorix_config,
               });
    exit;
}



# ============================================================
# creating a school
# ============================================================
# --create --school <name>
if ($school ne "" and $create==1){
    if (not exists $sophomorix_config{'SCHOOLS'}{$school}){
        print "\n";
        print "WARNING: You must add the school \"$school\" in\n";
        print "         $DevelConf::file_conf_sophomorix\n";
        print "         before you can create it!\n\n";
        exit;
    } else {
        # create new school in AD
        &AD_school_create({ldap=>$ldap,
                           root_dse=>$root_dse,
                           root_dns=>$root_dns,
                           school=>$school,
                           smb_admin_pass=>$smb_admin_pass,
                           sophomorix_config=>\%sophomorix_config,
                           sophomorix_result=>\%sophomorix_result,
                         });
    }
    exit;
}



# ============================================================
# mounting/umounting a school
# ============================================================
# --mount <school>
if ($mount ne ""){
    &mount_school($mount,$root_dns,$smb_admin_pass,\%sophomorix_config);
    exit;
}



# --umount <school>
if ($umount ne ""){
    &umount_school($umount,$root_dns,\%sophomorix_config);
    exit;
}



# --listmount
if ($listmount==1){
    &testmount_school("","",\%sophomorix_config,1);
    exit;
}



# ============================================================
# recreating all schools
# ============================================================
# --create-all-schools
if ($create_all_schools==1){
    foreach my $school (keys %{$sophomorix_config{'SCHOOLS'}}) {
        # create new ou
        &AD_school_create({ldap=>$ldap,
                           root_dse=>$root_dse,
                           root_dns=>$root_dns,
                           school=>$school,
                           smb_admin_pass=>$smb_admin_pass,
                           sophomorix_config=>\%sophomorix_config,
                           sophomorix_result=>\%sophomorix_result,
                         });
    }
    exit;
}



# ============================================================
# killing a school
# ============================================================
# --kill --school <name>
if ($school ne "" and $kill==1){
    print "\nNot implemented\n\n";
}


############################################################
# gpo
############################################################

# --gpo-listall
if ($gpo_listall==1){
    if ($json==0){
        $json=1;
    }
    my $ref_gpo=&AD_gpo_listall({sophomorix_config=>\%sophomorix_config,
                                 sophomorix_result=>\%sophomorix_result,
		               });
    &json_dump({json => $json,
                jsoninfo => "GPOS",
                jsoncomment => "All GPOs of the samba server",
                log_level => $Conf::log_level,
                hash_ref=>$ref_gpo,
                sophomorix_config=>\%sophomorix_config,
               });

    exit;
}


# --gpo-create
if ($gpo_create ne ""){
    if (not exists $sophomorix_config{'SCHOOLS'}{$gpo_create}){
        print "\n";
        print "WARNING: You must add the school \"$gpo_create\" in\n";
        print "         $DevelConf::file_conf_sophomorix\n";
        print "         before you can create a gpo for it!\n\n";
        exit;
    } else {
        &AD_gpo_create({ldap=>$ldap,
                        root_dse=>$root_dse,
                        root_dns=>$root_dns,
                        gpo=>$gpo_create,
                        gpo_type=>"school",
                        smb_admin_pass=>$smb_admin_pass,
                        sophomorix_config=>\%sophomorix_config,
                        sophomorix_result=>\%sophomorix_result,
                      });
  
        exit;
    }
}



# --gpo-kill
if ($gpo_kill ne ""){
    &AD_gpo_kill({ldap=>$ldap,
                  root_dse=>$root_dse,
                  root_dns=>$root_dns,
                  gpo=>$gpo_kill,
                  gpo_type=>"school",
                  smb_admin_pass=>$smb_admin_pass,
                  sophomorix_config=>\%sophomorix_config,
                  sophomorix_result=>\%sophomorix_result,
                });
    exit;
}

# --gpo-dump ... --gpo-dump-type ... --gpo-dump-path ... 
if ($gpo_dump ne "" and $gpo_dump_type ne "" and $gpo_dump_path ne ""){
    &AD_gpo_dump({ldap=>$ldap,
                  root_dse=>$root_dse,
                  root_dns=>$root_dns,
                  gpo_dump=>$gpo_dump,
                  gpo_dump_type=>$gpo_dump_type,
                  gpo_dump_path=>$gpo_dump_path,
                  smb_admin_pass=>$smb_admin_pass,
                  sophomorix_config=>\%sophomorix_config,
                  sophomorix_result=>\%sophomorix_result,
                });
    exit;
}




&AD_unbind_admin($ldap);

&log_script_end(\@arguments,\%sophomorix_result,\%sophomorix_config,$json);



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

# 
################################################################################


sub _smbclient_testfile {
    my ($share,$testfile)=@_;
    my $file_exists=0;
    my $smbclient_command=$sophomorix_config{'INI'}{'EXECUTABLES'}{'SMBCLIENT'}.
        " -U ".$DevelConf::sophomorix_file_admin."%'".$smb_admin_pass."'".
        " //$root_dns/$share -c 'ls'";
    my $stdout=`$smbclient_command 2> /dev/null`;
    my $return=${^CHILD_ERROR_NATIVE}; # return of value of last command
    my @lines=split(/\n/,$stdout);
    foreach my $line (@lines){
        my ($unused,$file,@unused)=split(/\s+/,$line);
	if (defined $file){
	    if ($file eq $testfile){
		$file_exists=1;
		last;
	    }
	}
    }
    if ($file_exists==1){
        print "      OK: File $testfile exists on share $share\n ";
    }  else {
        print "  NOT OK: File $testfile does NOT exist on share $share\n ";
    }
}



sub _smbcquotas_testshare {
    my ($share)=@_;
    my $smbcquotas_command=$sophomorix_config{'INI'}{'EXECUTABLES'}{'SMBCQUOTAS'}.
        " -U ".$DevelConf::sophomorix_file_admin."%'******'".
        " -F //$root_dns/$share";
        my ($return_quota)=&smb_command($smbcquotas_command,$smb_admin_pass);
        if ($return_quota==0){
	    print "      OK: smbcquotas -F returned $return_quota\n ";
	}  else {
	    print "    NOT OK: smbcquotas -F failed with $return_quota\n ";
	}
}



sub _smb_msdfs {
    my ($share)=@_;
    if (exists $sophomorix_config{'samba'}{'net_conf_list'}{$share}{'msdfs root'}){
	print "      OK: msdfs root = ".
              $sophomorix_config{'samba'}{'net_conf_list'}{$share}{'msdfs root'}.
              "\n ";
    } else {
        print "    NOT OK: msdfs root option on ".$share." NOT set to yes/no\n";
    }
}
