#!/usr/bin/perl -w
# $Id$
# This Script (watch-my-home) was created by Rüdiger Beck
# It is released under the GPL Version 3
# For Bugs send mail to (jeffbeck-at-web.de)

# todo
# skip some dirs
# pop warning also on renames
# Nachteil: kurzzeitig ist das Programm aus


# Bibliotheken
use strict;
use utf8;
use Glib qw/TRUE FALSE/;
use Gtk2 '-init';
use Linux::Inotify2;
use File::Basename;
use File::Copy;
use File::Path;
# use log names of perl variables, i.e. $UID
use English;
use Log::Log4perl qw(:easy);
# wait, before starting watch
sleep 10;

# configure logging
my $log="/tmp/watch-my-home.log";

my $home=$ENV{'HOME'};
my $UID_name=getpwuid($UID);
my $EUID_name=getpwuid($EUID);
my ($GID_name)=getgrgid($GID);
my ($EGID_name)=getgrgid($EGID);

my $script="watch-my-home-".$UID_name;
my $scriptname="watch-my-home";

my $label_feedback;
# allow everybody to log int the logfile
umask 000;
Log::Log4perl->easy_init({ 
                level   => $INFO,
                file    => ">>$log" } );    


my $config_file = "/etc/linuxmuster-client/extras/watch-my-home.conf";
{package WatchConf ; do $config_file || die "ERROR: $config_file not found or readable\n"} 

my $no_warning_abs=$home."/".$WatchConf::no_warning_dir;
print "Saving in $WatchConf::no_warning_dir is OK\n";
print "Logfile is $log\n";


INFO "##################################################";
INFO "$script started (pid=$PROCESS_ID)";
&kill_other_scripts();
INFO "\$HOME: $home";
INFO "UID:  $UID_name ($UID)\n";
INFO "EUID: $EUID_name ($EUID)\n";
INFO "GID:  $GID_name ($GID)\n";
INFO "EGID: $EGID_name ($EGID)\n";

############################################################
# Configuration
############################################################
# dir to watch (must be directory)
my $dir=$home;
my $new_home_file="/tmp/heimatverzeichnis";

############################################################
# Script
############################################################
### Define an Inotify2 instance
INFO "Watching:   $dir \n";
if (not -e $dir){
    INFO "Watching $dir does not exist";
    exit;
}

# works
my $inotify = new Linux::Inotify2
or die "Unable to create new inotify object: $!";
$inotify->watch ( $dir, IN_CREATE)
or die "watch creation failed";




my $kidpid = fork();
my $dead_kid=0;
if (not defined $kidpid) {
    print "No resources\n";
} elsif ($kidpid == 0) {
    INFO "Child process started with pid $PROCESS_ID";
    &watcher();
} else {
    INFO "Parent process started with pid $PROCESS_ID";
    &user_change();
    # do not wait for child, kill it
    &kill_other_scripts();
    # wait for child
    #my $dead_kid = waitpid($kidpid,0);
    INFO "Parent process will end now";
}



sub watcher {
    while() {
        my @events = $inotify->read;
        unless ( @events > 0 ) {
            print "read error: $!";
            last;
        }
        foreach( @events ) {
            my $abs_path=$_->fullname;
            # path rel to home
            my $home_path=$abs_path;
            $home_path=~s/$home\///;

            INFO "Created: $abs_path ($home_path)\n";
            if ( $home_path=~/^\..*/ ){
                # do nothing with dotfiles
                print "$abs_path is a dotfile\n";
            } elsif ($home_path=~/^[Mm][Aa][Gg][Ii][Cc][Kk]/){
                # do nothing
            } elsif ($home_path eq "missfont.log"){
                # do nothing
            } elsif (-l $abs_path){
              # Do something with the link
                INFO "Link created:     $abs_path ($home_path)\n";
  	        &show_message_dialog(undef,
                   "warning",
                   "Sie haben den Link <b>$home_path</b> ausserhalb von $WatchConf::no_warning_dir angelegt.\n\n".
                   "Der Link <b>$home_path</b> wird auf dem Rechner an dem Sie sitzen gespeichert und kann z.B. durch".
                   " synchronisiertes Starten von anderen gelöscht werden!\n\n".
                   "Wenn Sie den Link <b>$home_path</b> dauerhaft  auf dem Server abspeichern wollen, ".
                   "müssen Sie ihn in $WatchConf::no_warning_dir anlegen.\n",
                   'ok',
                   $home_path);
            } elsif (-f $abs_path){
                # Do something with the file
                INFO "File created:     $abs_path ($home_path)\n";
  	        &show_message_dialog(undef,
                   "warning",
                   "Sie haben die Datei <b>$home_path</b> ausserhalb von $WatchConf::no_warning_dir gespeichert.\n\n".
                   "Die Datei <b>$home_path</b> wird auf dem Rechner an dem Sie sitzen gespeichert und kann z.B. durch".
                   " synchronisiertes Starten von anderen gelöscht werden!\n\n".
                   "Wenn Sie die Datei <b>$home_path</b> dauerhaft auf dem Server abspeichern wollen, ".
                   "müssen Sie sie in $WatchConf::no_warning_dir speichern.\n",
                   'ok',
                   $home_path);
            } elsif (-d $abs_path){
              # Do something with the dir
                INFO "Dir created:     $abs_path ($home_path)\n";
  	        &show_message_dialog(undef,
                   "warning",
                   "Sie haben den Ordner <b>$home_path</b> ausserhalb von $WatchConf::no_warning_dir angelegt.\n\n".
                   "Der Ordner <b>$home_path</b> wird auf dem Rechner an dem Sie sitzen gespeichert und kann z.B. durch".
                   " synchronisiertes Starten von anderen gelöscht werden!\n\n".
                   "Wenn Sie den Ordner <b>$home_path</b> und seinen Inhalt dauerhaft auf dem Server abspeichern wollen, ".
                   "müssen Sie ihn in $WatchConf::no_warning_dir anlegen.\n",
                   'ok',
                   $home_path);
            } else{
              # Do something with the non-dir, non-file, non-link
                INFO "Something created:     $abs_path ($home_path)\n";
  	        &show_message_dialog(undef,
                   "warning",
                   "Sie haben <b>$home_path</b> ausserhalb von $WatchConf::no_warning_dir angelegt.\n\n".
                   "Bitte beachten Sie, dass <b>$home_path</b> dort nach dem Abmelden gelöscht wird!\n\n".
                   "Dauerhaft zu speichernde Dinge müssen nach $WatchConf::no_warning_dir gespeichert werden.\n",
                   'ok',
                   $home_path);
              }
        }
    }
}



sub user_change{
    while (){
        if (-e "$new_home_file"){
            my $new_home=&get_new_home();
            #INFO "Userchange($PROCESS_ID): $new_home ($home)";
            if ($new_home ne $home){
                INFO "Userchange($PROCESS_ID): user has changed -> terminate";
                return;
            } else {
                # INFO "Userchange($PROCESS_ID): user unchanged -> waiting";
            }
        } else {
            INFO "Userchange($PROCESS_ID): cannot read $new_home_file";
        }
        sleep 5;
    }
}






sub kill_other_scripts {    
    INFO "Killing all other scripts:";
    my $pid_string=`pgrep -f $scriptname`;
    my (@pids) = split("\n",$pid_string);
    foreach my $pid (@pids){
        if (not $pid==$PROCESS_ID){
            my $string=`ps -o cmd= -p $pid`;
            if ($string=~/perl/){
                # make sure its the script
                INFO "Killing $scriptname with $pid";
                system("kill $pid && echo '   ---> Killed succesfully' >> $log || echo '   ---> ERROR killing $pid' >> $log");
            } else {
                INFO "NOT Killing $string";
            }
        }
    }
}



sub get_new_home{
    my $new_home=`cat $new_home_file`;
    chomp($new_home);
    return $new_home;
}


sub show_message_dialog_old {
    #THIS IS THE MAIN FEATURE OF THE APP:
    #you tell it what to display, and how to display it
    #$parent is the parent window, or "undef"
    #$icon can be one of the following:	a) 'info'
    #					b) 'warning'
    #					c) 'error'
    #					d) 'question'
    #$text can be pango markup text, or just plain text, IE the message
    #$button_type can be one of the following: 	a) 'none'
    #						b) 'ok'
    #						c) 'close'
    #						d) 'cancel'
    #						e) 'yes-no'
    #						f) 'ok-cancel'

    my ($parent,$icon,$text,$button_type) = @_;
 
    my $dialog = Gtk2::MessageDialog->new (undef,
					'destroy-with-parent',
					"warning",
					"ok",
					sprintf "$text");
		
    # this will typically return certain values depending on the 
    # value of $retval.
    # in this application, we only change the label's value accordingly
    my $response = $dialog->run;
    print "Antwort: $response";
    $dialog->destroy; # tut nicht
    print "done\n";
    system ("/usr/bin/watch-my-home &");
    exit;
}



sub show_message_dialog {
    my ($undef,$type,$text,$button_type,$file) = @_;
    system("/usr/bin/zenity --$type --text='$text'");
    #exit;
}

