#!/usr/bin/perl -w
# This script (sophomorix-belwue) 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 IMAP::Admin;
#use DBI;
#use utf8;
use HTML::TableExtract;
use Net::LDAP;
use JSON;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Useqq = 1;
$Data::Dumper::Terse = 1; 

use Sophomorix::SophomorixBase qw(
                                 print_line
                                 print_title
                                 log_script_start
                                 log_script_end
                                 log_script_exit
                                 check_options
                                 get_passwd_charlist
                                 get_plain_password
                                 config_sophomorix_read
                                 result_sophomorix_init
                                 result_sophomorix_add
                                 result_sophomorix_check_exit
                                 result_sophomorix_print
                                 json_dump
                                 );

use Sophomorix::SophomorixSambaAD qw(
                                 AD_bind_admin
                                 AD_unbind_admin
                                 AD_dns_get
                                 AD_get_user
                                 AD_get_AD_for_check
                                 AD_get_passwd
                                    );

my @arguments = @ARGV;

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

# Variablen für Optionen
$Conf::log_level=1;
my $help=0;
my $info=0;
my $json=0;
my $school="default-school";

my $dump_belwue_html=0;
my $skip_addressbook=0;

my $parse_belwue_data=0;
my $caller_copy="";

my $show_object="";
my $show_mailforwarding=0;
my $show_maillist_admins=0;

my $dump_config=0;
my $dump_belwue=0;
my $dump_action=0;

# data hashes
my %belwue=();
my %Action=();

# paths
my $config_path="/etc/linuxmuster/sophomorix";
my $config_basename="belwue-mail.conf";

system("mkdir -p /var/lib/sophomorix/belwue"); 

# Parsen der Optionen
my $testopt=GetOptions(
           "help|h" => \$help,
           "info|i" => \$info,
           "json|j+" => \$json,
           "verbose|v+" => \$Conf::log_level,
           "dump-belwue-html" => \$dump_belwue_html,
           "skip-addressbook" => \$skip_addressbook,
           "parse-belwue-data" => \$parse_belwue_data,
           "caller-copy|callercopy=s" => \$caller_copy,
           "show-object=s" => \$show_object,
           "show-mailforwarding" => \$show_mailforwarding,
           "show-maillist-admins" => \$show_maillist_admins,
           "dump-config" => \$dump_config,
           "dump-belwue" => \$dump_belwue,
           "dump-action" => \$dump_action,
           "school=s" => \$school,
          );

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

my $config_file;
if ($school eq "default-school"){
    $config_file=$config_path."/".$school."/".$config_basename;
} else {
    $config_file=$config_path."/".$school."/".$school.".".$config_basename;
}


############################################################
# Reading Configuration
############################################################
my ($ldap,$root_dse) = &AD_bind_admin(\@arguments,\%sophomorix_result,$json);
my $root_dns=&AD_dns_get($root_dse);

# exit if user does not exist
my $school_AD_caller;
my $home_directory_AD_caller;
if ($caller_copy ne ""){
    my ($firstname_utf8_AD,$lastname_utf8_AD,$adminclass_AD,$existing_AD,$exammode_AD,$role_AD,
        $home_directory_AD,$user_account_control_AD,$toleration_date_AD,$deactivation_date_AD,
        $school_AD,$status_AD,$firstpassword_AD,$unid_AD)=
    &AD_get_user({ldap=>$ldap,
                  root_dse=>$root_dse,
                  root_dns=>$root_dns,
                  user=>$caller_copy,
                });
    if ($existing_AD eq "FALSE"){
        print "\nERROR: User $caller_copy does not exist\n\n";
        exit 88;
    }
    if ($school ne $school_AD){
        print "\nERROR: User $caller_copy is in school $school_AD, not $school\n\n";
        exit 88;        
    }
    $school_AD_caller=$school_AD;
    $home_directory_AD_caller=$home_directory_AD;
}

# read sophomorix conf
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);
# read belwue conf
my %conf=&read_config($config_file);

# calculate connect data
$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASE'}="CN=".$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'BASE'};
$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}=$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'BASE'};
$conf{'SCHOOL'}{$school}{'CONNECT'}{'SCOPE'}="sub";
$conf{'SCHOOL'}{$school}{'CONNECT'}{'FILTER'}="(cn=*)";
$conf{'SCHOOL'}{$school}{'CONNECT'}{'HOST'}=$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'PROTOCOL'}."://".
                                          $conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'SERVER'}.":".
                                          $conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'PORT'};
$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINUSER'}=$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'BELWUE_ACCOUNT'}{'ADMINUSER'};
$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINURL'}=$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'BELWUE_ACCOUNT'}{'ADMINURL'};
$conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'}=$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'BELWUE_ACCOUNT'}{'PASSWORD'};
$conf{'SCHOOL'}{$school}{'CONNECT'}{'SERVER'}=$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'BELWUE_ACCOUNT'}{'SERVER'};
my ($adminuser,$maildomain)=split(/\@/,$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'BELWUE_ACCOUNT'}{'ADMINUSER'});
$conf{'SCHOOL'}{$school}{'CONNECT'}{'MAILDOMAIN'}=$maildomain;
$conf{'SCHOOL'}{$school}{'CONNECT'}{'WGET_OPTIONS'}=$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'WGET'}{'WGET_OPTIONS'};

# calculate paths
$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}="/var/lib/sophomorix/belwue/".$school."/downloads";
$conf{'SCHOOL'}{$school}{'PATHS'}{'RESULTS'}="/var/lib/sophomorix/belwue/".$school."/results";
$conf{'SCHOOL'}{$school}{'PATHS'}{'UPLOAD_MULTIMAILBOXES'}="/var/lib/sophomorix/belwue/".$school."/results/multimailboxes_utf8.txt";


############################################################
# --help
############################################################
if ($help==1) {
   # Scriptname ermitteln
   my @list = split(/\//,$0);
   my $scriptname = pop @list;
   # Befehlsbeschreibung
   print('
sophomorix-belwue

Options
  -h  / --help
  -i  / --info
  -j  / --json
  -v  / --verbose
  -vv / --verbose --verbose

  --school <schoolname> (defaut is default-school)

  Download data to /var/lib/sophomorix/belwue/<school>/downloads/:
    --dump-belwue-html (download and parse: port 9010/636 needs to be open)
      --skip-addressbook (i. e. if port 636 is closed)

  Parse downloaded data OFFLINE and create results in /var/lib/sophomorix/belwue/<school>/results/:
  --parse-belwue-data (parse already downloaded data, and show what to do)
    This results in the following files:
      * multimailboxes_utf8.txt  
        (ONE file to create missing mailboxes at belwue: Admin-Login -> Obkjekte -> Konten importieren)
      * maillist_<name>.txt
        (ONE file per maillist to update mailist members: Mailingliste -> Tab:Mitglieder -> Importieren)
  --caller-copy <user>
    (copy the result files in the home of a user <user>)

  Analyze data further and show specific output:  
  --show-object <object_name>   (object can be mailbox, maillist, ....)
  --show-mailforwarding         (overview to counteract mailforwarding to UNsafe harbor, UNprivacy shield)
  --show-maillist-admins        (overview to find the admin of a mailinglist)

  Dumping data as JSON Object for debugging:
  --dump-config -j    (dump processed configuration)
  --dump-belwue -j    (dump data parsed from downloaded html files)
  --dump-action -j    (dump what to do)


Quick introduction:
  1) Run: 
     sophomorix-belwue / sophomorix-belwue --school <schoolname>
     to see what config file you need.
  2) Create configfile and change password (other config stuff should be OK)
  3) Run:
     sophomorix-belwue --school <schoolname> --dump-belwue-html
     This downloads data from belwue: 
        A) The ldap adressbook at belwue (via port 636)
        B) Downloads html pages from the CommuniGate admin webinterface (via port 9010)
  4) You can analyze and access the downloaded data OFFLINE with:
     sophomorix-belwue --school <schoolname> --parse-belwue-data
  5) For specic output use the options above



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



# --info
if ($info==1) {


}

##################################################
# Script starts here
##################################################
my @password_chars=&get_passwd_charlist();


# --dump-belwue-html / --parse-belwue-data
if ($dump_belwue_html==1 or $parse_belwue_data){
    ############################################################
    # get ldap address book
    ############################################################ 
    print "\n";
    print "============================================================\n";
    if ($skip_addressbook==1){
        print "Skipping download of belwue Addressbook:\n";
    } else {
        print "Accessing belwue address book:\n";
        my ($ldap) = &bind_admin();
        if($Conf::log_level>=2){
            print "  Searching for data in Belwue address book via ldap\n";
            print "    SEARCHBASE: $conf{'SCHOOL'}{$school}{'CONNECT'}{'BASE'}\n";
            print "    SCOPE: $conf{'SCHOOL'}{$school}{'CONNECT'}{'SCOPE'}\n";
            print "    FILTER: $conf{'SCHOOL'}{$school}{'CONNECT'}{'FILTER'}\n";
        }
        my $mesg = $ldap->search(
                       base   => $conf{'SCHOOL'}{$school}{'CONNECT'}{'BASE'},
                       scope => $conf{'SCHOOL'}{$school}{'CONNECT'}{'SCOPE'},
                       filter => $conf{'SCHOOL'}{$school}{'CONNECT'}{'FILTER'},
                            );

        my $max = $mesg->count; 
        my $count = $mesg->count;
        for( my $index = 0 ; $index < $max ; $index++) {
            my $num=$index+1;
            my $entry = $mesg->entry($index);
            my $dn=$entry->dn();
            my $uid=$entry->get_value('UID');
            my $cn=$entry->get_value('cn');
            my $given=$entry->get_value('givenName');
            my $sn=$entry->get_value('sn');
            my $server=$entry->get_value('hostServer');
            my $mail=$entry->get_value('mail');

            if (not defined $given){
                $given="";
            }
            if($Conf::log_level>=3){
	        print "$num) dn: $dn\n";
	        print "   * CN:          $cn\n";
	        print "   * givenName:   $given\n";
   	        print "   * hostServer:  $server\n";
	        print "   * mail:        $mail\n";
	        print "   * sn:          $sn\n";
	        print "   * UID:         $uid\n";
                print "\n";
            }
            $belwue{'objects'}{$uid}{'CN'}=$cn;
            $belwue{'objects'}{$uid}{'givenName'}=$given;
            $belwue{'objects'}{$uid}{'hostServer'}=$server;
            $belwue{'objects'}{$uid}{'mail'}=$mail;
            $belwue{'objects'}{$uid}{'sn'}=$sn;
            $belwue{'objects'}{$uid}{'UID'}=$uid;
        }
        #print Dumper(%belwue);

        print "$max entries found via ldaps\n";
        print "============================================================\n";
        &unbind_admin($ldap);
    } 
    ############################################################
    # downloading objects
    ############################################################ 
    if ($parse_belwue_data==0){
        print "Downloading and parsing html files:\n";
        system("mkdir -p $conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}");

        # object list
        my $download_objects_command="wget ".
           "$conf{'SCHOOL'}{$school}{'CONNECT'}{'WGET_OPTIONS'} ".
           "-q --http-user=admin ".
           "--http-password=$conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'} ".
           "--output-document=".$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/objects.html ".
           "\"https://$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINURL'}/$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}".
           "/ObjectList.html?domainName=$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}\"";

        if($Conf::log_level>=2){
            print "\nWGET: $download_objects_command\n\n";
        }
        my $return=system($download_objects_command);
        &wget_return($download_objects_command,
                     $return,
                     "Objects",
                     "$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}/objects.html");
    }

    ############################################################
    # parsing objects
    ############################################################

    # file to parse
    my $html_doc = $conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/objects.html";
    print "* Parsing all objects $html_doc:\n";

    # list of headers
    my $table_headers = [ 'Objekt', 'Typ','Speicher','Letzter Zugriff' ];

    # constructor
    my $table_extract = HTML::TableExtract->new(headers => $table_headers);
    $table_extract->utf8_mode(1);
    $table_extract->parse_file($html_doc);
    my ($table) = $table_extract->tables;

    foreach my $row ($table->rows) {
        my ($object,$type,$storage,$access)=@$row;
        if (not defined $storage){
            $storage="none";
        } else {
#	    if ($type eq "Multi-Mailbox"){
#		push @{ $belwue{'LISTS'}{'Multi-Mailbox'} }, $object;
#		$belwue{'objects'}{$object}{'QUOTA_USED'}=$storage;
#	    } elsif ($type eq "Alias") {
#		$belwue{'objects'}{$object}{'UID'}=$storage;
#		push @{ $belwue{'LISTS'}{'Alias'} }, $object;
#	    } elsif ($type eq "Gruppe") {
#		$belwue{'objects'}{$object}{'MEMBER_COUNT'}=$storage;
#		push @{ $belwue{'LISTS'}{'Gruppe'} }, $object;
#	    } elsif ($type eq "Mailingliste") {
#		push @{ $belwue{'LISTS'}{'Mailingliste'} }, $object;
#	    }
	}
        if (not defined $access){
            $access="never";
        } else {
	    if ($type eq "Multi-Mailbox"){
		$belwue{'objects'}{$object}{'LAST_ACCESS'}=$access;
	    } elsif ($type eq "Alias") {
                # nothing to do
	    } elsif ($type eq "Gruppe") {
                # nothing to do
	    }
	}
	#print "   * Extracted row: $object  $type  $storage  $access\n";
        $belwue{'objects'}{$object}{'TYPE'}=$type;
        # add to types
        if ($type eq "Mailingliste"){
            $belwue{'maillist'}{$object}{'TYPE'}=$type;
	    push @{ $belwue{'LISTS'}{'Mailingliste'} }, $object;
            #push @maillists, $object;
            ############################################################
            # downloading maillist data
            ############################################################
            if ($parse_belwue_data==0){
                my $download_list_command="wget ".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'WGET_OPTIONS'} ".
                    "-q --http-user=admin ".
                    "--http-password=$conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'} ".
                    "--output-document=".$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object.html ".
                    "\"https://$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINURL'}/".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}".
                    "/Subscribers.html?InCluster=1&domainName=".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}&&listName=$object\"";
                if($Conf::log_level>=2){
                    print "\nWGET: $download_list_command\n\n";
                }
                my $return=system($download_list_command);
                &wget_return($download_list_command,
                             $return,
                             $object,
                             "$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}/$object.html");
	    }

            ############################################################
            # parsing maillist data
            ############################################################
            my $html_doc = $conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object.html";
            print "* Parsing object $html_doc\n";

            # list of headers
            # Umlaut in header does not work
            my $table_headers = [ 'Email',
                                  'Zustellungsart',
                                  'Anmeldezeit',
                                  'Nachrichten'];
            # constructor
            my $table_extract = HTML::TableExtract->new(headers => $table_headers);
            $table_extract->utf8_mode(1);
            $table_extract->parse_file($html_doc);
            my ($table) = $table_extract->tables;
	    my $row_count=0;
            my $empty_row=0;
            foreach my $row ($table->rows) {
		$row_count++;
                my ($member_email,$type,$time,$bounced,$displayname)=@$row;
		if (not defined $member_email){
		    $empty_row=1;
                    next;
		}
                my ($uid,$domain)=split(/\@/,$member_email);

                if ($type ne "Abonnement aufheben"){
                    $belwue{'maillist'}{$object}{'MEMBERS'}{$member_email}="member";
                    if ($domain eq $conf{'SCHOOL'}{$school}{'CONNECT'}{'MAILDOMAIN'}){
			$belwue{'objects'}{$uid}{'MAILLIST_MEMBERSHIP'}{$object}=$type;
			$belwue{'objects'}{$object}{'MEMBERS'}{$uid}=$type;
		    } else {
			# foreign domain, nothing to do
		    }
                    push @{ $belwue{'maillist'}{$object}{'MEMBERLIST'} }, $member_email;
                    push @{ $belwue{'objects'}{$object}{'MEMBER'}{'LIST'} }, $member_email;
                } else {
		    $belwue{'warnings'}{$uid}{'MAILLIST_MEMBERSHIP_WARNING'}{$object}=$type;
		}
		$belwue{'objects'}{$uid}{'MAILLIST_MEMBERSHIP_CREATED'}{$object}=$time;
		$belwue{'objects'}{$uid}{'MAILLIST_MESSAGES_BOUNCED'}{$object}=$bounced;
            }
	    if ($empty_row==0){
		print "  * $row_count rows parsed\n";
	    } else {
		print "  * $row_count empty row parsed\n";
	    }
            # sort the memberlist if not empty
            if ( not  $#{ $belwue{'maillist'}{$object}{'MEMBERLIST'} }==-1 ){
                 @{ $belwue{'maillist'}{$object}{'MEMBERLIST'} } = sort @{ $belwue{'maillist'}{$object}{'MEMBERLIST'}  };
            }
            if ( not  $#{ $belwue{'objects'}{$object}{'MEMBER'}{'LIST'} }==-1 ){
		@{ $belwue{'objects'}{$object}{'MEMBER'}{'LIST'} } = sort @{ $belwue{'objects'}{$object}{'MEMBER'}{'LIST'}  };
		$belwue{'objects'}{$object}{'MEMBER'}{'COUNT'} = $#{ $belwue{'objects'}{$object}{'MEMBER'}{'LIST'} };
            }
	    
        } elsif ($type eq "Gruppe"){
            $belwue{'GROUP'}{$object}{'TYPE'}=$type;
	    push @{ $belwue{'LISTS'}{'Gruppe'} }, $object;
	    $belwue{'objects'}{$object}{'MEMBER_COUNT'}=$storage;
            ############################################################
            # downloading group data
            ############################################################
            if ($parse_belwue_data==0){
                my $download_list_command="wget ".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'WGET_OPTIONS'} ".
                    "-q --http-user=admin ".
                    "--http-password=$conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'} ".
                    "--output-document=".$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object.html ".
                    "\"https://$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINURL'}/".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}".
                    "/Group.html?&domainName=".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}&&groupName=$object\"";
                if($Conf::log_level>=2){
                    print "\nWGET: $download_list_command\n\n";
                }
                my $return=system($download_list_command);
                &wget_return($download_list_command,
                             $return,
                             $object,
                             "$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}/$object.html");
	    }

            ############################################################
            # parsing group data
            ############################################################
            my $html_doc = $conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object.html";
            print "* Parsing group file $html_doc\n";

            my $string=`cat $html_doc | grep input | grep Members | grep value`;
            my (@lines)=split(/\n/,$string);
	    foreach my $line (@lines){
		my ($unused1,$used)=split("value=",$line);
		my ($member_mail,$unused2)=split(" ",$used);
		$member_mail=~s/"//g;
		if ($member_mail ne ""){
                    my ($uid,$domain)=split(/\@/,$member_mail);
		    if (not defined $domain or
                        $domain eq $conf{'SCHOOL'}{$school}{'CONNECT'}{'MAILDOMAIN'}
                       ){
                        $belwue{'objects'}{$uid}{'GROUP_MEMBERSHIP'}{$object}=$type;
                        $belwue{'objects'}{$object}{'MEMBERS'}{$uid}="member";
                    } else {
                        $belwue{'objects'}{$object}{'MEMBERS'}{$member_mail}="member";
                    }
		}
	    }
        } elsif ($type eq "Alias"){
            $belwue{'ALIAS'}{$object}=$storage;
            $belwue{'ALIAS_REVERSE'}{$storage}=$object;
            # aliases are in storage column
            $belwue{'objects'}{$storage}{'ALIAS'}=$object;
		$belwue{'objects'}{$object}{'UID'}=$storage;
		push @{ $belwue{'LISTS'}{'Alias'} }, $object;


	} elsif ($type eq "Multi-Mailbox"){
            $belwue{'multimailbox'}{$object}{'TYPE'}="Multi-Mailbox";
            $belwue{'multimailbox'}{$object}{'STORAGE'}=$storage;
            $belwue{'multimailbox'}{$object}{'ACCESS'}=$access;
	    $belwue{'objects'}{$object}{'UID'}=$storage;
	    push @{ $belwue{'LISTS'}{'Multi-Mailbox'} }, $object;

            ############################################################
            # downloading Multi-Mailbox Settings
            ############################################################
            if ($parse_belwue_data==0){
                my $download_list_command="wget ".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'WGET_OPTIONS'} ".
                    "-q --http-user=admin ".
                    "--http-password=$conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'} ".
                    "--output-document=".$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object-settings.html ".
                    "\"https://$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINURL'}/".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}".
                    "/AccountSettings.html?&domainName=".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}&&accountName=$object\"";
                if($Conf::log_level>=2){
                    print "\nWGET: $download_list_command\n\n";
                }
                my $return=system($download_list_command);
                &wget_return($download_list_command,
                             $return,
                             $object,
                             "$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}/$object.html");
	    }
            ############################################################
            # parsing Multi-Mailbox Settings
            ############################################################
            my $html_object_settings = $conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object-settings.html";
            print "* Parsing htmp page $html_object_settings \n";

	    # extract maillist admin box from table
            my $te = HTML::TableExtract->new( depth => 5, count => 10 );
	    $te->utf8_mode(1);
            $te->parse_file($html_object_settings);
            foreach my $ts ($te->tables) {
                #print "Table found at ", join(',', $ts->coords), ":\n";
		my $row_count=0;
                foreach my $row ($ts->rows) {
		    $row_count++;
		    my ($maillist)=@$row;
		    $maillist=&Sophomorix::SophomorixBase::remove_embracing_whitespace($maillist);
		    if ($maillist eq "Name" or $maillist eq ""){
                        next;
		    } else {
			push @{ $belwue{'objects'}{$object}{'ADMINISTRATED_MAILLIST'}{'LIST'} }, $maillist;
			$belwue{'objects'}{$maillist}{'ADMIN'}=$object;
		    }
                }
            }
	    @{ $belwue{'objects'}{$object}{'ADMINISTRATED_MAILLIST'}{'LIST'} } =
		sort @{ $belwue{'objects'}{$object}{'ADMINISTRATED_MAILLIST'}{'LIST'} };
            $belwue{'objects'}{$object}{'ADMINISTRATED_MAILLIST'}{'COUNT'} =
		$#{ $belwue{'objects'}{$object}{'ADMINISTRATED_MAILLIST'}{'LIST'} }+1;

            ############################################################
            # downloading Multi-Mailbox Mail Settings
            ############################################################
            if ($parse_belwue_data==0){
                my $download_list_command="wget ".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'WGET_OPTIONS'} ".
                    "-q --http-user=admin ".
                    "--http-password=$conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'} ".
                    "--output-document=".$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object-mailsettings.html ".
                    "\"https://$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINURL'}/".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}".
                    "/AccountMailSettings.html?&domainName=".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}&&accountName=$object\"";
                if($Conf::log_level>=2){
                    print "\nWGET: $download_list_command\n\n";
                }
                my $return=system($download_list_command);
                &wget_return($download_list_command,
                             $return,
                             $object,
                             "$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}/$object.html");
	    }
            ############################################################
            # parsing Multi-Mailbox Mail Settings
            ############################################################
            # nothing so far

            ############################################################
            # downloading Multi-Mailbox Mail Rules
            ############################################################
            if ($parse_belwue_data==0){
                my $download_list_command="wget ".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'WGET_OPTIONS'} ".
                    "-q --http-user=admin ".
                    "--http-password=$conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'} ".
                    "--output-document=".$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object-mailrules.html ".
                    "\"https://$conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINURL'}/".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}".
                    "/AccountMailInRules.html?&domainName=".
                    "$conf{'SCHOOL'}{$school}{'CONNECT'}{'BASESIMPLE'}&&accountName=$object\"";
                if($Conf::log_level>=2){
                    print "\nWGET: $download_list_command\n\n";
                }
                my $return=system($download_list_command);
                &wget_return($download_list_command,
                             $return,
                             $object,
                             "$conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}/$object.html");
	    }
            ############################################################
            # parsing Multi-Mailbox Mail Rules
            ############################################################
            my $html_settings_doc = $conf{'SCHOOL'}{$school}{'PATHS'}{'DOWNLOADS'}."/$object-mailrules.html";
            print "* Parsing htmp page $html_settings_doc \n";

            # extract forwarding box from table
            my $te2 = HTML::TableExtract->new( depth => 5, count => 3 );
	    $te2->utf8_mode(1);
            $te2->parse_file($html_settings_doc);
            foreach my $ts ($te2->tables) {
                #print "Table found at ", join(',', $ts->coords), ":\n";
		my $row_count=0;
                foreach my $row ($ts->rows) {
		    $row_count++;
		    my ($text,@unneeded)=@$row;
		    my @lines=split(/\s+/,$text);
		    my $line_count=0;
		    foreach my $target (@lines){
			$line_count++;
			if (defined $target and $target ne "" and $row_count==1){
			    push @{ $belwue{'objects'}{$object}{'MAILFORWARDING'}{'LIST'} }, $target;
			}
		    }
		    # show the row
                    #print "EXTRACT   ", join(',', @$row), "\n";
                }
            }
	    if (exists $belwue{'objects'}{$object}{'MAILFORWARDING'}{'LIST'}){
                $belwue{'objects'}{$object}{'MAILFORWARDING'}{'COUNT'}=
		    $#{ $belwue{'objects'}{$object}{'MAILFORWARDING'}{'LIST'} }+1;
	    } else {
                $belwue{'objects'}{$object}{'MAILFORWARDING'}{'COUNT'}=0;
	    }
        } else {
            print "Unknown object $type\n";
        }
    }
    
    ############################################################
    # printout data/write data into files
    ############################################################
    system("mkdir -p $conf{'SCHOOL'}{$school}{'PATHS'}{'RESULTS'}");
    # cleaning up previous result
    system("rm $conf{'SCHOOL'}{$school}{'PATHS'}{'RESULTS'}/*");
    open (MULTIMAILBOX, ">$conf{'SCHOOL'}{$school}{'PATHS'}{'UPLOAD_MULTIMAILBOXES'}");
    print MULTIMAILBOX "Name\tRealname\tType\tPassword\tStorage\tAliases\n";

    &json_dump({json => $json,
                jsoninfo => "BELWUE",
                jsoncomment => "Data dumped from BelWue",
                log_level => $Conf::log_level,
                hash_ref=>\%belwue,
                sophomorix_config=>\%sophomorix_config,
               });

    # fetch AD data
    my ($ref_AD_check) = &AD_get_AD_for_check({ldap=>$ldap,
                                               root_dse=>$root_dse,
                                               root_dns=>$root_dns,
                                               admins=>"FALSE",
                                               sophomorix_config=>\%sophomorix_config,
                                             });

    #print Dumper($ref_AD_check);

    ############################################################
    # CALCULATE REQUIRED_MAILBOXES from belwue.conf
    ############################################################
    my (@adminclasses) = split(/,/,$conf{'SCHOOL'}{$school}{$config_basename}{'MAILBOX'}{'ADMINCLASS'});
    foreach my $adminclass (@adminclasses){
         $adminclass=&Sophomorix::SophomorixBase::remove_embracing_whitespace($adminclass);
	 $conf{'SCHOOL'}{$school}{'MAILBOX'}{'CONF'}{'ADMINCLASS'}{$adminclass}="from conf";
    }
    my (@users) = split(/,/,$conf{'SCHOOL'}{$school}{$config_basename}{'MAILBOX'}{'USERS'});
    foreach my $user (@users){
         $user=&Sophomorix::SophomorixBase::remove_embracing_whitespace($user);
	 $conf{'SCHOOL'}{$school}{'MAILBOX'}{'CONF'}{'USERS'}{$user}="from conf";
    }
    my (@onlymailboxes) = split(/,/,$conf{'SCHOOL'}{$school}{$config_basename}{'MAILBOX'}{'ONLYMAILBOX'});
    foreach my $onlymailbox (@onlymailboxes){
         $onlymailbox=&Sophomorix::SophomorixBase::remove_embracing_whitespace($onlymailbox);
	 $conf{'SCHOOL'}{$school}{'MAILBOX'}{'CONF'}{'ONLYMAILBOX'}{$onlymailbox}="from conf";
    }
    foreach my $sam ( keys %{ $ref_AD_check->{'LOOKUP_by_school'}{$school}{'user_BY_sAMAccountName'} } ) {
	if ($ref_AD_check->{'sAMAccountName'}{$sam}{'sophomorixSchoolname'} eq $school){
	    # ADMINCLASS
	    if (exists $conf{'SCHOOL'}{$school}{'MAILBOX'}{'CONF'}{'ADMINCLASS'}{$ref_AD_check->{'sAMAccountName'}{$sam}{'sophomorixAdminClass'}}){
		$Action{$school}{'REQUIRED_MAILBOXES'}{$sam}{'ADMINCLASS'}="TRUE";
	    }
            # USERS
	    if (exists $conf{'SCHOOL'}{$school}{'MAILBOX'}{'CONF'}{'USERS'}{$sam}){
		$Action{$school}{'REQUIRED_MAILBOXES'}{$sam}{'USERS'}="TRUE";
	    }
	}
    }
    # add onlymailbox
    foreach my $sam ( keys %{ $conf{'SCHOOL'}{$school}{'MAILBOX'}{'CONF'}{'ONLYMAILBOX'} } ) {
        $Action{$school}{'REQUIRED_MAILBOXES'}{$sam}{'ONLYMAILBOX'}="TRUE";
    }

    ############################################################
    # calculate mailboxes to add
    ############################################################
    foreach my $sam ( keys %{ $Action{$school}{'REQUIRED_MAILBOXES'} } ) {
	if (exists $belwue{'multimailbox'}{$sam}){
            # nothing to do
	} else {
	    if (exists $Action{$school}{'REQUIRED_MAILBOXES'}{$sam}{'ONLYMAILBOX'} and
		$Action{$school}{'REQUIRED_MAILBOXES'}{$sam}{'ONLYMAILBOX'} eq "TRUE"){
                # skip this user, should be created with the WEBUI of belwue
                next;
	    }
            $Action{$school}{'ADD_MAILBOXES'}{$sam}{'ADD'}="TRUE";
	    my $last=$ref_AD_check->{'sAMAccountName'}{$sam}{'sn'};
	    my $given=$ref_AD_check->{'sAMAccountName'}{$sam}{'givenName'};
	    my $plain_password;
	    if ($conf{'SCHOOL'}{$school}{$config_basename}{'MAILBOX'}{'PASSWORD'} eq "sophomorixFirstPassword"){
		$plain_password=$ref_AD_check->{'sAMAccountName'}{$sam}{'sophomorixFirstPassword'};
	    } elsif ($conf{'SCHOOL'}{$school}{$config_basename}{'MAILBOX'}{'PASSWORD'}>6) {
                $plain_password=&get_plain_password(
                        "teacher",
                        "",
                        "TRUE", # TRUE/FALSE/birthday
                        $conf{'SCHOOL'}{$school}{$config_basename}{'MAILBOX'}{'PASSWORD'}, # length of random pwd
                        "",
                        \%sophomorix_config,
                        @password_chars);

	    } else {
                print "Misconfigured [MAILBOX]-> PASSWORD (must be sophomorixFirstPassword|number larger than 6)\n";
		exit;
	    }
	    my $type="MultiMailbox";
	    my $mailquota=$conf{'SCHOOL'}{$school}{$config_basename}{'MAILBOX'}{'MAILQUOTA'};
	    if (not defined $sam or
		not defined $given or
                not defined $last or
                not defined $type or
                not defined $plain_password or
                not defined $mailquota
		){
                next;
	    }
	    my $alias=$ref_AD_check->{'sAMAccountName'}{$sam}{'sophomorixFirstnameASCII'}.
		      ".".
	  	      $ref_AD_check->{'sAMAccountName'}{$sam}{'sophomorixSurnameASCII'};
	    $alias=~tr/A-Z/a-z/; # make lowercase
	    my $line="$sam\t$given $last\t$type\t$plain_password\t${mailquota}\t$alias\n";
	    print MULTIMAILBOX "$line";
	}
    }

    ############################################################
    # calculate mailboxes to delete
    ############################################################
    foreach my $sam ( keys %{ $belwue{'multimailbox'} } ) {
	if (exists $Action{$school}{'REQUIRED_MAILBOXES'}{$sam} ){
            # nothing to do
	} else {
            $Action{$school}{'DELETE_MAILBOXES'}{$sam}{'DELETE'}="TRUE";
	    foreach my $group ( keys %{ $belwue{'objects'}{$sam}{'GROUP_MEMBERSHIP'} } ) {
              $Action{$school}{'DELETE_MAILBOXES'}{$sam}{'GROUP_MEMBERSHIP'}{$group}="$sam is group member";  
	    }
	    foreach my $group ( keys %{ $belwue{'objects'}{$sam}{'MAILLIST_MEMBERSHIP'} } ) {
              $Action{$school}{'DELETE_MAILBOXES'}{$sam}{'MAILLIST_MEMBERSHIP'}{$group}="$sam is maillist member";  
	    }
	}
    }


    ############################################################
    # CALCULATE MANAGED MAILLISTS from belwue.conf
    ############################################################
    my (@entries) = split(/,/,$conf{'SCHOOL'}{$school}{$config_basename}{'MAILLIST'}{'MANAGED_ADMINCLASS_LIST'});
    foreach my $entry (@entries){
	my ($item,$maillist)=split(/=/,$entry);
	my (@adminclasses)=split(/\|/,$item);
	foreach my $adminclass (@adminclasses){
	    $adminclass=&Sophomorix::SophomorixBase::remove_embracing_whitespace($adminclass);
	    if (not defined $maillist){
                $maillist=$adminclass;
	    } else {
    	        $maillist=&Sophomorix::SophomorixBase::remove_embracing_whitespace($maillist);
	    }
	    $conf{'SCHOOL'}{$school}{'MAILLIST'}{'CONF'}{'MAILLIST_by_ADMINCLASS'}{$adminclass}{$maillist}="member";
	    $conf{'SCHOOL'}{$school}{'MAILLIST'}{'CONF'}{'ADMINCLASS_by_MAILLIST'}{$maillist}{$adminclass}="member";
	}
    }

    foreach my $maillist ( keys %{ $conf{'SCHOOL'}{$school}{'MAILLIST'}{'CONF'}{'ADMINCLASS_by_MAILLIST'} }){
        $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'UPDATE'}="FALSE";
    }

    ############################################################
    # calculate maillist memberships to add/maillists to modify 
    ############################################################
    # decide which users to add to maillist
    foreach my $sam ( keys %{ $ref_AD_check->{'LOOKUP_by_school'}{$school}{'user_BY_sAMAccountName'} } ) {
	my $adminclass=$ref_AD_check->{'sAMAccountName'}{$sam}{'sophomorixAdminClass'};
	if (exists $conf{'SCHOOL'}{$school}{'MAILLIST'}{'CONF'}{'MAILLIST_by_ADMINCLASS'}{$adminclass}){
	    foreach my $maillist ( keys %{ $conf{'SCHOOL'}{$school}{'MAILLIST'}{'CONF'}{'MAILLIST_by_ADMINCLASS'}{$adminclass} }){
	        $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'MEMBERS'}{$sam}="REASON: Adminclass $adminclass";
                # check if member already
	        if (exists $belwue{'objects'}{$sam}{'MAILLIST_MEMBERSHIP'}{$maillist}){
                    $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'KEEP'}{$sam}="$sam is already correct member";
	        } else {
		    $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'UPDATE'}="TRUE";
                    $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'ADD'}{$sam}="ADD $sam to $maillist, REASON: member of $adminclass";
  	        }
	    }
	}
    }

    # decide which users to delete from maillist
    foreach my $maillist ( keys %{ $conf{'SCHOOL'}{$school}{'MAILLIST'}{'CONF'}{'ADMINCLASS_by_MAILLIST'} }){
	foreach my $member ( @{ $belwue{'maillist'}{$maillist}{'MEMBERLIST'} }){
            my $sam=$member;
	    # remove trailing MAILDOMAIN to get sAMAccountName
            $sam=~s/\@$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'BASE'}$//g;
	    if ($sam eq $member){
		# do not care about users in another MAILDOMAIN
                next;
	    }
            if (exists $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'MEMBERS'}{$sam}){
                # OK members are aleady configured, exit if not
		if (not exists $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'KEEP'}{$sam}){
                    print "Strange things happen to $sam in $maillist\n";
		    exit;
		}
	    } else {
		$Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'UPDATE'}="TRUE";
                $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'REMOVE'}{$sam}="REMOVE $sam from $maillist";
	    }
	}
    }

    foreach my $maillist ( keys %{ $conf{'SCHOOL'}{$school}{'MAILLIST'}{'CONF'}{'ADMINCLASS_by_MAILLIST'} }){
	my @keys=("MEMBERS","ADD","REMOVE","KEEP");
	foreach my $key (@keys){
	    my @list=();
	    foreach my $item ( keys %{ $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{$key} }){
		push @list,$item;
	    }
	    $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'COUNT'}{$key}=$#list+1;
	}
    }

    
#    print Dumper(%Action);
#    exit;
#   print Dumper(%conf);
#   print Dumper(%belwue);
#    exit;
    close(MULTIMAILBOX);

    ############################################################
    # SUMMARY
    ############################################################
    print "\nSUMMARY OF WHAT TO DO:\n";
    ############################################################
    # MAILBOXES
    ############################################################
    my @add_mailboxes=();
    foreach my $add_mailboxes (keys %{ $Action{$school}{'ADD_MAILBOXES'} }){
        push @add_mailboxes, $add_mailboxes;
    }
    @add_mailboxes = sort @add_mailboxes;
    my $add_mailbox_count=$#add_mailboxes+1;
    print "Add $add_mailbox_count Mailboxes:\n";
    foreach my $sam (@add_mailboxes){
        print "   * $sam\n";
    }

    my @delete_mailboxes=();
    foreach my $delete_mailboxes (keys %{ $Action{$school}{'DELETE_MAILBOXES'} }){
        push @delete_mailboxes, $delete_mailboxes;
    }
    @delete_mailboxes = sort @delete_mailboxes;
    my $delete_mailbox_count=$#delete_mailboxes+1;
    print "Delete $delete_mailbox_count Mailboxes:\n";
    foreach my $sam (@delete_mailboxes){
        print "   * $sam\n";
    }

    ############################################################
    # SHOW MAILLISTS
    ############################################################
    my $line="+---------------------------+---------+--------+--------+--------+\n";
    my @update_maillists=();
    foreach my $maillist ( keys %{ $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'} }){
	if ($Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'UPDATE'} eq "TRUE"){
            push @update_maillists,$maillist;
	}
    }

    @update_maillists = sort @update_maillists;

    print "\n";
    print "Update the following Maillists by uploading the members file:\n";
    if($Conf::log_level>=2){
        foreach my $maillist (@update_maillists){
            print "------------------------------------------------------------\n";
            print " Maillist: $maillist:\n";
            print "------------------------------------------------------------\n";
	    my @keys=("MEMBERS","ADD","REMOVE","KEEP");
	    foreach my $key (@keys){
	        my @list=();
	        foreach my $item ( keys %{ $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{$key} }){
		    push @list,$item;
	        }
                @list = sort @list;
		print "   ${key}:\n";
		foreach my $item (@list){
                    print "     * ".$item."@".$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'BASE'}."\n";
		}
	    }
	}
    } else {
        print $line;
        print    "| Maillist                  | MEMBERS |    ADD | REMOVE |   KEEP |\n";
        print $line;
        foreach my $maillist (@update_maillists){
	    printf "| %-26s|%8s |%7s |%7s |%7s |\n",
		$maillist,
	   	$Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'COUNT'}{'MEMBERS'},
	        $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'COUNT'}{'ADD'},
		$Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'COUNT'}{'REMOVE'},
	        $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'COUNT'}{'KEEP'} ;
        }
        print $line;
    }

    ############################################################
    # CREATE MAILLIST FILES
    ############################################################
    foreach my $maillist (@update_maillists){
	# create file
        my $maillist_file=$conf{'SCHOOL'}{$school}{'PATHS'}{'RESULTS'}."/maillist_".$maillist.".txt";
	my @members=();
	open (MAILLIST, ">$maillist_file");
	foreach my $member ( keys %{ $Action{$school}{'REQUIRED_MAILLIST_MEMBERSHIPS'}{$maillist}{'MEMBERS'} }){
	    push @members,$member;
	}
        @members = sort @members;
	foreach my $member (@members){
            print MAILLIST $member."@".$conf{'SCHOOL'}{$school}{'belwue-mail.conf'}{'ADRESSBOOK'}{'BASE'}."\n";
	}
        close(MAILLIST);

    }


    
    ############################################################
    # COPY RESULTS TO USER
    ############################################################
    # --caller-copy (do the copy stuff)
    if ($caller_copy ne ""){
	print "\n";
        &print_title("Copying files to user $caller_copy in school $school_AD_caller");
        my $smb_dir_home=$home_directory_AD_caller;
        $smb_dir_home=~s/\\/\//g;
        my ($string1,$rel_path_home)=split(/$school_AD_caller/,$smb_dir_home); # to home
        $rel_path_home=$rel_path_home."/sophomorix-belwue";
	my $lcd="/var/lib/sophomorix/belwue/".$school_AD_caller."/results/";
        my $smbclient_command=$sophomorix_config{'INI'}{'EXECUTABLES'}{'SMBCLIENT'}.
        " -U ".$DevelConf::sophomorix_file_admin."%'******'".
        " //$root_dns/$school_AD_caller ".
        " -c 'md \"$rel_path_home\"; cd \"$rel_path_home\"; lcd \"$lcd\";".
        " prompt; mput *.txt; exit;'";
        &Sophomorix::SophomorixBase::smb_command($smbclient_command,$smb_admin_pass);
	print "\n";
    }

    ############################################################
    # DISPLAY SPECIFIC RESULTS
    ############################################################
    # sort lists
    @{ $belwue{'LISTS'}{'Multi-Mailbox'} } = sort @{ $belwue{'LISTS'}{'Multi-Mailbox'} };
    @{ $belwue{'LISTS'}{'Alias'} } = sort @{ $belwue{'LISTS'}{'Alias'} };
    @{ $belwue{'LISTS'}{'Gruppe'} } = sort @{ $belwue{'LISTS'}{'Gruppe'} };
    @{ $belwue{'LISTS'}{'Mailingliste'} } = sort @{ $belwue{'LISTS'}{'Mailingliste'} };

    ############################################################
    # --show-object
    ############################################################
    if ($show_object ne ""){
        #print Dumper($belwue{'objects'}{$show_object});
        # pretty output
        my $json_obj = JSON->new->allow_nonref;
        my $utf8_pretty_printed = $json_obj->pretty->encode( $belwue{'objects'}{$show_object} );
        print "$utf8_pretty_printed\n";
    }

    ############################################################
    # --show-mailforwarding
    ############################################################
    if ($show_mailforwarding==1){
        print "================================================================================\n";
        my $entry=0;
	foreach my $mailbox (@{ $belwue{'LISTS'}{'Multi-Mailbox'} }){
	    if ($belwue{'objects'}{$mailbox}{'MAILFORWARDING'}{'COUNT'}>0){
                $entry++;
		my $adminclass;
		if (defined $ref_AD_check->{'sAMAccountName'}{$mailbox}{'sophomorixAdminClass'}){
                    $adminclass=$ref_AD_check->{'sAMAccountName'}{$mailbox}{'sophomorixAdminClass'};
		} else {
                    $adminclass="not in AD";
		}
		my $name;
		if (defined $belwue{'objects'}{$mailbox}{'CN'}){
                    $name=$belwue{'objects'}{$mailbox}{'CN'};
		} elsif (defined $belwue{'objects'}{$mailbox}{'ALIAS'}){
                    $name=$belwue{'objects'}{$mailbox}{'ALIAS'};
		} else {
                    $name="no CN/alias at belwue";
		}

		print "$entry) $mailbox ($name, AD: $adminclass)\n";
		foreach my $forward (@{ $belwue{'objects'}{$mailbox}{'MAILFORWARDING'}{'LIST'} }){
                    print "   $mailbox  --> $forward\n";
		}
	    }
	}
        print "================================================================================\n";
    }

    ############################################################
    # --show-maillist-admins
    ############################################################
    if ($show_maillist_admins==1){
	print "\n\nMailinglisten-Admins:\n";
	my $line="+-------+-----+---------------------------------------------------------------+\n";
        print $line;
	printf "| %-6s| %3s | %-62s|\n","Admin","n","Mailingliste";
        print $line;
	
        my $entry=0;
	foreach my $maillist (@{ $belwue{'LISTS'}{'Mailingliste'} }){
	    printf "| %-6s| %3s | %-62s|\n",$belwue{'objects'}{$maillist}{'ADMIN'},"n",$maillist;
	}
        print $line;
    }

    #print Dumper ($ref_AD_check);
    # print Dumper (%Action);
    # print Dumper(\%belwue{'LISTS'});
    
    #if($Conf::log_level>=2){
    #    print Dumper(\%belwue);
    #    my $ref_belwue=\%belwue;
    #}
} 


############################################################
# DEBUGGING OUTPUT
############################################################

# --dump-config
if ($dump_config==1){
    &json_dump({json => $json,
                jsoninfo => "CONFIG",
                jsoncomment => "The Config hash",
                log_level => $Conf::log_level,
                hash_ref=>\%conf,
                sophomorix_config=>\%sophomorix_config,
              });
}

# --dump-belwue
if ($dump_belwue==1){
    &json_dump({json => $json,
                jsoninfo => "BELWUE",
                jsoncomment => "BelWue data dump",
                log_level => $Conf::log_level,
                hash_ref=>\%belwue,
                sophomorix_config=>\%sophomorix_config,
              });
}

# --dump-action
if ($dump_action==1){
    &json_dump({json => $json,
                jsoninfo => "ACTION",
                jsoncomment => "The Action hash",
                log_level => $Conf::log_level,
                hash_ref=>\%Action,
                sophomorix_config=>\%sophomorix_config,
              });
}





############################################################
# subs
############################################################

sub bind_admin {
    # bind
    if($Conf::log_level>=2){
        print "  Connecting to Belwue via ldaps\n";
        print "    HOST:      $conf{'SCHOOL'}{$school}{'CONNECT'}{HOST} \n";
        print "    BIND-DN:   $conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINUSER'} \n";
        print "    PASSWORD:  $conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'}\n";
    }
    my $ldap = Net::LDAP->new($conf{'SCHOOL'}{$school}{'CONNECT'}{HOST}) or
        die "\nERROR: Connection to $conf{'SCHOOL'}{$school}{'CONNECT'}{HOST} failed!\n",
            " USER: $conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINUSER'}, PASSWORD: $conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'}\n\n";

    my $mesg = $ldap->bind($conf{'SCHOOL'}{$school}{'CONNECT'}{'ADMINUSER'}, 
                      password => $conf{'SCHOOL'}{$school}{'CONNECT'}{'PASSWORD'});
    # show errors from bind
    $mesg->code && die $mesg->error;
    return ($ldap);
}



######################################################################
sub unbind_admin {
    my ($ldap) = @_;
    my $mesg = $ldap->unbind();
    #  show errors from unbind
    $mesg->code && die $mesg->error;
}



######################################################################
sub wget_return {
    my ($command,$return,$object,$file)=@_;
    if ($return==0){
        print "   * Succesfully downloded html page for $object: $file\n";
    } else {
        print "   * ERROR downloading $object: wget returned error code $return\n";
        print "     $command\n";
        exit;
    }
}



######################################################################
sub read_config {
    my ($file) = @_;
    my %conf=();
    my $ref_conf=\%conf;
    if (-e $file) {
        tie %{ $ref_conf->{'SCHOOL'}{$school}{'belwue-mail.conf'} }, 'Config::IniFiles',
            ( -file => $file, 
              -handle_trailing_comment => 1,
            );
    } else {
        print "\n\nConfig file $file must be created with:\n\n";
        system ("cat /usr/share/sophomorix-belwue/config-templates/belwue-mail.conf.template.ini");
        exit;
    }
    return %conf;
}

