#!/usr/bin/perl use lib qw(/usr/lib/libDrakX); # i18n: IMPORTANT: to get correct namespace (drakguard instead of libDrakX) BEGIN { unshift @::textdomains, 'drakguard' } use strict; use diagnostics; use common; use standalone; use mygtk2; use ugtk2 qw(:create :helpers :wrappers); use Gtk2::SimpleList; use interactive; use network::shorewall; use network::squid; use services; use Encode; my $dansguardian_main_file = "/etc/dansguardian/dansguardian.conf"; my $dansguardian_filter_file = "/etc/dansguardian/dansguardianf1.conf"; my $time_control_file = "/etc/shorewall/time_control"; my $dansguardian_bannedsitelist = "/etc/dansguardian/lists/bannedsitelist"; my $dansguardian_exceptionsitelist = "/etc/dansguardian/lists/exceptionsitelist"; my $dansguardian_protected_program_list = "/etc/dansguardian/lists/blacklists/drakguard/protected_list"; my $msec_conf = "/etc/security/msec/perms.conf"; my $perms_orig = "/etc/security/msec/perms.orig"; my %dansguardian_levels = ( 160 => N_("Low"), 100 => N_("Normal"), 50 => N_("High"), ); my %dansguardian_langs = ( arspanish => 'es_AR', bulgarian => 'bg', chinesebig5 => 'zh_TW', chinesegb2312 => 'zh_CN', czech => 'cs', danish => 'da', dutch => 'nl', french => 'fr', german => 'de', hebrew => 'he', hungarian => 'hu', indonesian => 'id', italian => 'it', japanese => 'ja', lithuanian => 'lt', malay => 'ms', mxspanish => 'es_MX', polish => 'pl', portuguese => 'pt', ptbrazilian => 'pt_BR', #russian-1251 'russian-koi8-r' => 'ru', slovak => 'sk', spanish => 'es', swedish => 'sv', turkish => 'tr', ukenglish => 'en', ); my $blacklist_url_file = "/etc/dansguardian/lists/blacklists/drakguard/urls"; my $whitelist_url_file = "/etc/dansguardian/lists/whitelists/drakguard/urls"; my ($enable, $level, $time_control, $time_start_h, $time_start_m, $time_stop_h, $time_stop_m, $allow_time_change, $net_control, $not_net_control, $program_control, $net_control_state, $program_control_state); my $shorewall = network::shorewall::read(); my $proxy_port = 3128; my $proxy_user = 'squid'; my $guardian_port = 8080; my $guardian_user = 'dansguardian'; load(); my $toolname = 'drakguard'; my $title = N("Parental Control"); my $icon = 'drakguard'; $ugtk2::wm_icon = $icon; my $w = ugtk2->new($title); #- so that transient_for is defined, for wait messages and popups to be centered $::main_window = $w->{real_window}; my $in = interactive->vnew('su'); my $allusers_list = Gtk2::SimpleList->new(N("All users") => 'text'); $allusers_list->get_selection->set_mode('multiple'); @{$allusers_list->{data}} = sort(list_users()); my $allusers_program_list; my $users_program_list; my $users_list = Gtk2::SimpleList->new(N("Allowed users") => 'text'); $users_list->get_selection->set_mode('multiple'); @{$users_list->{data}} = difference2($shorewall->{accept_local_users}{http}, [ $proxy_user ]); my @url_lists = ( { tab_title => N("Blacklist"), list_title => N("Forbidden addresses"), remove_text => N("Remove from blacklist"), file => $blacklist_url_file, apply => \&apply_blacklist, }, { tab_title => N("Whitelist"), list_title => N("Allowed addresses"), remove_text => N("Remove from whitelist"), file => $whitelist_url_file, apply => \&apply_whitelist, }, { tab_title => N("Block programs"), list_title => N("Programs with blocked execution"), remove_text => N("Remove from blocked execution list"), file => $dansguardian_protected_program_list, apply => \&apply_block_program, } ); sub update_time_change() { gtkval_modify(\$allow_time_change, $enable && $time_control); gtkval_modify(\$net_control_state, $enable && $net_control); gtkval_modify(\$not_net_control, $enable && !$net_control); gtkval_modify(\$program_control_state, $enable && $program_control); } sub update_network_change() { gtkval_modify(\$not_net_control, $enable && !$net_control); gtkval_modify(\$net_control_state, $enable && $net_control); } sub update_program_state() { gtkval_modify(\$program_control_state, $enable && $program_control); } $w->{ok_clicked} = \&save; $w->{cancel_clicked} = \&quit_gui; gtkadd($w->{window}, gtknew('VBox', spacing => 5, children => [ $::isEmbedded ? () : (0, Gtk2::Banner->new($icon, $title)), 1, gtknew('Notebook', children => [ gtknew('Label', text => N("Configuration")), gtknew('VBox', spacing => 5, border_width => 5, children => [ 0, gtknew('Label', text => N("This tool allows to configure parental control.\nIt can block access to web sites and restrict connection during a specified timeframe.")), 0, gtknew('CheckButton', text => N("Enable parental control"), active_ref => \$enable, toggled => \&update_time_change), 1, gtknew('Label'), 0, gtknew('Title2', label => N("Main options")), 0, gtknew('HBox', children_tight => [ gtknew('CheckButton', text => N("Block all network traffic"), sensitive_ref => \$enable, active_ref => \$net_control, toggled => \&update_network_change), ]), 0, gtknew('HBox', children_tight => [ gtknew('Label', sensitive_ref => \$enable, text_markup => N("Obscenity sensibility"), #Sensitivity to bad words alignment => [ 0, 0.5 ]), gtknew('ComboBox', list => [ keys %dansguardian_levels ], text_ref => \$level, sensitive_ref => \$enable, format => sub { translate($dansguardian_levels{$_[0]}) }), ]), 1, gtknew('Label'), 0, gtknew('Title2', label => N("User access")), 0, gtknew('HBox', spacing => 5, children_tight => [ gtknew('ScrolledWindow', width => 220, height => 120, child => $allusers_list), gtknew('VBox', spacing => 5, children_tight => [ gtknew('Button', stock => "gtk-add", clicked => \&add_user), gtknew('Button', stock => "gtk-remove", clicked => \&remove_user), ]), gtknew('ScrolledWindow', width => 220, height => 120, child => $users_list), ]), 1, gtknew('Label'), 0, gtknew('Title2', label => N("Time control")), 0, gtknew('CheckButton', text => N("Allow connections only between these times:"), active_ref => \$time_control, sensitive_ref => \$enable, toggled => \&update_time_change), 0, gtknew('HBox', sensitive_ref => \$allow_time_change, spacing => 20, children_tight => [ gtknew('Label', text => N("Start:")), gtknew('HBox', spacing => 2, children_tight => [ gtknew('SpinButton', lower => 0, upper => 23, step_increment => 1, value => $time_start_h, value_changed => sub { $time_start_h = $_[0]->get_value } ), gtknew('Label', text => ':'), gtknew('SpinButton', lower => 0, upper => 59, step_increment => 1, value => $time_start_m, value_changed => sub { $time_start_m = $_[0]->get_value } ), ]), gtknew('Label'), gtknew('Label', text => N("End:")), gtknew('HBox', spacing => 2, children_tight => [ gtknew('SpinButton', lower => 0, upper => 23, step_increment => 1, value => $time_stop_h, value_changed => sub { $time_stop_h = $_[0]->get_value } ), gtknew('Label', text => ':'), gtknew('SpinButton', lower => 0, upper => 59, step_increment => 1, value => $time_stop_m, value_changed => sub { $time_stop_m = $_[0]->get_value } ), ]), ]), ]), (map { my $url_list = $_; $url_list->{list} = Gtk2::SimpleList->new($url_list->{list_title} => 'text'); $url_list->{list}->get_selection->set_mode('multiple'); if ($url_list->{tab_title} eq N("Block programs")){@{$url_list->{list}{data}} = read_program_list($url_list->{file}); } else{@{$url_list->{list}{data}} = read_url_list($url_list->{file});} $allusers_program_list = Gtk2::SimpleList->new(N("Blocked users") => 'text'); $allusers_program_list->get_selection->set_mode('multiple'); @{$allusers_program_list->{data}} = sort(list_users()); $users_program_list = Gtk2::SimpleList->new(N("Allowed users") => 'text'); $users_program_list->get_selection->set_mode('multiple'); @{$users_program_list->{data}} = sort (read_program_user_list($url_list->{file})); my $entry; my $original_entry; ( gtknew('Label', if_($url_list->{tab_title} eq N("Whitelist"), sensitive_ref => \$net_control_state), if_($url_list->{tab_title} eq N("Blacklist"), sensitive_ref => \$not_net_control), if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$enable), text => $url_list->{tab_title}), gtknew('VBox', if_($url_list->{tab_title} eq N("Whitelist"), sensitive_ref => \$net_control_state), if_($url_list->{tab_title} eq N("Blacklist"), sensitive_ref => \$not_net_control), spacing => 5, children => [ 0, gtknew('HBox', children_tight => [ if_($url_list->{tab_title} eq N("Block programs"),gtknew('CheckButton', text => N("Block defined applications"), sensitive_ref => \$enable, active_ref => \$program_control, toggled => \&update_program_state)), ]), 0, gtknew('HBox', if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$program_control_state), border_width => 5, spacing => 5, children_loose => [ $entry = gtknew('Entry'), if_($url_list->{tab_title} eq N("Block programs"), gtknew('Button', text => N("..."), clicked => sub { $entry->set_text($in->ask_file(N("Please select the program you want to control"), "/var/lib/caixamagica/programas")); })), 0, gtknew('Button', text => N("Add"), clicked => sub { my $text = $entry->get_text; $text =~ s,^[^:]+://,,g; #- strip protocol if ($url_list->{tab_title} eq N("Block programs")) { $text =~ s,(\W?)$,,g; #- remove unknown caracters $original_entry = ""; $text = resolve_symlinks($text); if ( (grep { $_ && m/^\[Desktop Entry\]\s*/g} chomp_(cat_($text))) || $text =~ m/\.desktop/g) {# make this only for application block my @exec_line = grep { $_ && m/^Exec=(.*)\s*/g} chomp_(cat_($text)); require lang; my $locale = lang::read(); $locale = lc($locale->{country}); my @system_name = grep { $_ && m/^GenericName(\[$locale\])?=(.*)\s*/g} chomp_(cat_($text)); foreach (@exec_line){ my ($exec, $text, $args) = /(^Exec=)(\w+)\s*(.*)/; if ($text eq ""){ ($exec, $text, $args) = /(^Exec=)(.*+)\s*(.*)/;} } foreach my $b (@system_name){ $original_entry = $b; $original_entry =~ s/^GenericName(\[$locale\])?=//g; $original_entry = Encode::decode("utf8", $original_entry); } } $text = `which $text 2> /dev/null` if $text ne ""; $text =~ s/\n//g; } if ( $text eq "" && $url_list->{tab_title} eq N("Block programs")) { $in->ask_warn(N("Error"), N("Invalid Binary Name")) and return; } else { if ($url_list->{tab_title} eq N("Block programs")) { list_add_entry_program($url_list->{list}, $text. " ( $original_entry )") if $original_entry ne ""; list_add_entry_program($url_list->{list}, $text) if $original_entry eq ""; } else { list_add_entry($url_list->{list}, $text); } } $entry->set_text(""); }), ]), 1, gtknew('ScrolledWindow', if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$program_control_state), width => 500, height => 150, child => $url_list->{list}), 0, gtknew('HButtonBox', if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$program_control_state), border_width => 5, layout => 'edge', children_loose => [ gtknew('Button', text => $url_list->{remove_text}, clicked => sub { list_remove_selected($url_list->{list}); }), ]), if_($url_list->{tab_title} eq N("Block programs"), 1, gtknew('Label'), 0, gtknew('Title2', label => N("Unblock users")), 0, gtknew('HButtonBox', sensitive_ref => \$program_control_state, spacing => 5, children_tight => [ gtknew('ScrolledWindow', width => 220, height => 120, child => $allusers_program_list), gtknew('VBox', spacing => 5, children_tight => [ gtknew('Button', stock => "gtk-add", clicked => \&add_user_program), gtknew('Button', stock => "gtk-remove", clicked => \&remove_user_program), ]), gtknew('ScrolledWindow', width => 220, height => 120, child => $users_program_list), ]), 0, gtknew('HBox'), ), ]), ); } @url_lists), ]), 0, $w->create_okcancel( undef, undef, undef, [ N("Help"), sub { run_program::raw({ detach => 1 }, 'drakhelp', '--id', $toolname) } ]), ]), ); $w->show; Gtk2->main; $w->exit(0); sub list_add_entry { my ($list, @addr) = @_; foreach my $a (@addr) { push @{$list->{data}}, $a unless any { $_->[0] eq $a } @{$list->{data}}; } } sub list_add_entry_program { my ($list, @addr) = @_; foreach my $a (@addr) { $b = $a; $a =~ s/\s(.*)//g; my @abc = map {$_->[0]} @{$list->{data}}; push @{$list->{data}}, $b unless (any { $_->[0] eq $b } @{$list->{data}}) || (grep {$_ && m/$a(.*)/g} @abc); } } sub list_remove_entry { my ($list, @addr) = @_; #- workaround buggy Gtk2::SimpleList array abstraction, it destroys references @{$list->{data}} = map { member($_->[0], @addr) ? () : [ @$_ ] } @{$list->{data}}; } sub list_get_selected { my ($list) = @_; uniq(map { $list->{data}[$_][0] } $list->get_selected_indices); } sub list_remove_selected { my ($list) = @_; list_remove_entry($list, list_get_selected($list)); } sub list_get_entries { my ($list) = @_; map { $_->[0] } @{$list->{data}}; } sub add_user() { list_add_entry($users_list, list_get_selected($allusers_list)); } sub remove_user() { list_remove_selected($users_list); } sub add_user_program() { list_add_entry($users_program_list, list_get_selected($allusers_program_list)); } sub remove_user_program() { list_remove_selected($users_program_list); } sub quit_gui { my ($o_code) = @_; $w->exit($o_code); } sub load() { my $guardian = read_dansguardian(); my $levelname = { %dansguardian_levels }->{$guardian->{naughtynesslimit}}; $net_control = $guardian->{netblock}; $program_control = $guardian->{programblock}; gtkval_modify(\$not_net_control, $enable && !$net_control); $level = { reverse %dansguardian_levels }->{$levelname} if $levelname; $level ||= { reverse %dansguardian_levels }->{High}; $enable = services::starts_on_boot('dansguardian'); $time_control = cat_($::prefix . "/etc/shorewall/start") =~ /^INCLUDE $time_control_file$/m; my @time_control_settings = grep { /\bnet2fw\b/ } cat_($::prefix . $time_control_file); my ($drop_start, $drop_stop); if (my ($drop_start_h, $drop_start_m) = top(@time_control_settings) =~ /\B--timestart\s(\d+):(\d+)\b/) { $drop_start = $drop_start_h*60 + $drop_start_m - 1; } if (my ($drop_stop_h, $drop_stop_m) = first(@time_control_settings) =~ /\B--timestop\s(\d+):(\d+)\b/) { $drop_stop = $drop_stop_h*60 + $drop_stop_m + 1; } if (defined($drop_start) && defined($drop_stop)) { my $day_time = 24*60; $drop_start = ($drop_start + $day_time) % $day_time; $drop_stop = ($drop_stop + $day_time) % $day_time; $time_start_h = int($drop_stop/60); $time_start_m = $drop_stop%60; $time_stop_h = int($drop_start/60); $time_stop_m = $drop_start%60; } $time_start_h //= 18; $time_start_m //= 0; $time_stop_h //= 21; $time_stop_m //= 0; } sub save() { my $_wait = $in->wait_message(N("Please wait"), N("Please wait")); network::shorewall::set_in_file('start', $enable && $time_control, "INCLUDE $time_control_file"); if ($enable && $time_control) { my $day_time = 24*60; #- start/stop dropping the minute after/before traffic is allowed #- and make sure times are positive and in the 00:00 <-> 23:59 interval my $drop_start = ($time_stop_h*60 + $time_stop_m + 1 + $day_time) % $day_time; my $drop_stop = ($time_start_h*60 + $time_start_m - 1 + $day_time) % $day_time; output_p($::prefix . $time_control_file, join('', map { my $chain = $_; map { sprintf("iptables -I $chain -j DROP -m time --timestart %02d:%02d --timestop %02d:%02d\n", int($_->[0]/60), $_->[0]%60, int($_->[1]/60), $_->[1]%60, ); } ($drop_stop >= $drop_start ? [ $drop_start, $drop_stop] : ([ 0, $drop_stop ], [ $drop_start, $day_time-1 ])); #- if allowing start time is before allowing stop time, #- we have to use two intervals to cover the completary parts of the day } qw(net2fw fw2net)), ); #- allowing from 00:00 to 23:59 is a special case that does not need rules $time_control = 0 if $drop_stop == $day_time - 1 && $drop_start == 0; } network::shorewall::set_in_file('start', $enable && $time_control, "INCLUDE $time_control_file"); if ($enable) { $in->do_pkgs->ensure_are_installed([ qw(shorewall squid dansguardian) ]) or quit_gui(1); $_->{apply}(list_get_entries($_->{list})) foreach @url_lists; write_dansguardian(); enable_transparent_proxy($proxy_port); #- reload shorewall config if it has just been installed $shorewall ||= network::shorewall::read(); } else { $program_control = 0; @url_lists[2]->{apply}(list_get_entries(@url_lists[2]->{list})); } services::set_status($_, $enable) foreach qw(squid dansguardian); if ($shorewall) { $shorewall->{disabled} = 0 if $enable; @{$shorewall->{accept_local_users}{http}} = if_($enable, uniq($proxy_user, list_get_entries($users_list))); @{$shorewall->{accept_local_users}{$proxy_port}} = if_($enable, $guardian_user); network::shorewall::set_redirected_ports($shorewall, 'tcp', $guardian_port, if_($enable, 'http', $proxy_port)); network::shorewall::write($shorewall, $in); } quit_gui(); } sub resolve_symlinks { # Check if a given file (either the pure filename or in a SANE device # string as ":") is a symlink, if so expand the link. # If the new file name is a link, expand again, until finding the # physical file. my ($file) = @_; my $prefix = ""; if ($file =~ m!^([^/]*)(/.*)$!) { $prefix = $1; $file = $2; } else { return $file; } while (1) { #my $ls = `ls -l $file 2> /dev/null`; my $ls = readlink $file; if ($ls =~ m!\s($file)\s*\->\s*(\S+)\s*$!) { my $target = $2; if ($target !~ m!^/! && $file =~ m!^(.*)/[^/]+$!) { $target = "$1/$target"; } $file = $target; } else { last; } } return $prefix . $file; } sub remove_acl { my ($file, $binary) = @_; `setfacl -b $binary`; clean_config_line($file, "$binary"); } sub set_permissions { my ($line, $line_info) = @_; #`protect $line --add`; chmod 0700, $line; chown "root","root", $line; #remove msec lines #clean_config_line($msec_conf,"$line"); subst_config_line($dansguardian_protected_program_list,"$line_info \n"); #adds the file to dansguardian_protected_program_list subst_config_line($msec_conf,"$line\troot.root\t700\tforce\t\n"); #adds the file to msec #`protect $line $_` foreach list_get_entries($users_program_list); #add msec line or lines... foreach my $user_msec (list_get_entries($users_program_list)) { my @msec_line = grep { $_ && m/$line/g} chomp_(cat_($msec_conf)); my @program_list_line = grep { $_ && m/^$line/g} chomp_(cat_($dansguardian_protected_program_list)); `setfacl -m u:$user_msec:r-x $line`; subst_config_line($dansguardian_protected_program_list,"$_$user_msec,\n") foreach @program_list_line; #adds the users to the programs blocked in msec subst_config_line($msec_conf,"$_$user_msec:r-x,\n") foreach @msec_line; #adds the users to the programs blocked in msec } } sub restore_permissions { my ($line) = @_; foreach ($line){ my ($fich, $usrname, $grpname, $mode) = /^(.*)\t(\w+)\.(\w+)\t(\d+)\s*/ or next; $mode = sprintf "%04d", $mode;#make number with 4 digits my $guid = getgrnam($grpname); my $uid = getpwnam($usrname); chown $uid, $guid, $fich; chmod oct($mode), $fich; } } sub subst_config_line { my ($file, $line) = @_; my $key = first(split(' ', $line)); my $done; substInFile { $done = 1 if s|^\s*$key\b.*\n|$line|; $_ .= $line if eof && !$done; } $file; } sub clean_config_line { my ($file, $line) = @_; my $key = first(split(' ', $line)); my $done; substInFile { $done = 1 if s|^\s*$key.*\n||; } $file; } sub block_internet_dansguardian { my ($file, $line) = @_; my $key = "#"; substInFile { s|^$key\*\*\s|**\n|; } $file; } sub unblock_internet_dansguardian { my ($file) = @_; my $key = "#"; substInFile { s|^\*\*\s|$key**\n|; } $file; } sub enable_transparent_proxy { my ($port) = @_; #- FIXME: use network::squid once it is rewritten to be more gentle with the config file subst_config_line($network::squid::squid_conf_file, "http_port $port transparent\n"); } #- mostly duplicated for MDK::Common::System::getVarsFromSh sub read_dansguardian() { my $guardian = {}; foreach (cat_($dansguardian_filter_file)) { s/#.*//; s/^\s*//; my ($v, $val) = /^(\w+)\s*=\s*(.*)/ or next; $val = $1 if $val =~ /^"(.*)"$/ || $val =~ /^'(.*)'$/; $guardian->{$v} = $val; } $guardian; } sub write_dansguardian() { require lang; my $locale = lang::read(); my $locale_lang = lang::getlocale_for_lang($locale->{lang}, $locale->{country}); my %lang_to_dansguardian = reverse %dansguardian_langs; my $dansguardian_lang = $lang_to_dansguardian{$locale_lang} || $lang_to_dansguardian{$locale->{lang}}; subst_config_line($dansguardian_main_file, "language = '$dansguardian_lang'\n") if $dansguardian_lang; subst_config_line($dansguardian_filter_file, "naughtynesslimit = '$level'\n"); subst_config_line($dansguardian_filter_file, "netblock = '$net_control'\n"); subst_config_line($dansguardian_filter_file, "programblock = '$program_control'\n"); if ($net_control) { block_internet_dansguardian($dansguardian_bannedsitelist); } else { unblock_internet_dansguardian($dansguardian_bannedsitelist); } } sub include_guardian_file { my ($guardian_file, $external_file) = @_; my $to_add = ".Include<$external_file>\n"; clean_config_line($guardian_file, "$to_add" ); my @all = cat_($guardian_file); if ((($dansguardian_bannedsitelist eq $guardian_file) && !$net_control) || (($dansguardian_exceptionsitelist eq $guardian_file) && $net_control)) { if (!member($to_add, @all)) { output_p($guardian_file, @all, $to_add); } } } sub read_url_list { my ($file) = @_; grep { $_ && !/^\s*#/ } chomp_(cat_($file)); } sub read_program_list { my ($file) = @_; grep { $_ && s/(\s*(\w+),)*//g } chomp_(cat_($file)); } sub read_program_user_list { my ($file) = @_; my @user_list = grep { $_ && s/(.*?)\s//g } chomp_(cat_($file)); uniq(map{ my $user = $_; $user =~ m/(\w+),/g;} @user_list); } sub apply_blacklist { my @addr = @_; my $blacklist_top = "/etc/dansguardian/lists/bannedsitelist"; my $blacklist_category = "blocked by Mandriva parental control tool"; output_p($blacklist_url_file, map { $_ . "\n" } qq(#listcategory: "$blacklist_category"), @addr); include_guardian_file($blacklist_top, $blacklist_url_file); } sub apply_whitelist { my @addr = @_; my $whitelist_top = "/etc/dansguardian/lists/exceptionsitelist"; output_p($whitelist_url_file, map { $_ . "\n" } @addr); include_guardian_file($whitelist_top, $whitelist_url_file); } sub apply_block_program { #my @addr = @_; #output_p($acl_file, map { $_ . "\n" } @addr); if ($program_control) { my @original_list = read_program_list(@url_lists[2]->{file}); my @orig_list = read_program_list(@url_lists[2]->{file}); for (@original_list){ s/\s(.*)//; } my @actual_list = list_get_entries(@url_lists[2]->{list}); my @act_list = list_get_entries(@url_lists[2]->{list}); for (@actual_list){ s/\s(.*)//; } #code to make diff bettween vectors my (@union, @intersection, @difference); my $element; @union = @intersection = @difference = (); my %count = (); foreach $element (@original_list, @actual_list) { $count{$element}++ }; foreach $element (keys %count) { # push @union, $element; push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element; } if (scalar(@difference)) { #keep the permissons save, make the way to do that my $diff; foreach $diff (@difference) { my @orig_file = cat_($perms_orig); my @progs_orig_file = grep { $_ && m/$diff/g } chomp_(cat_($perms_orig)); #test if program is in msec my @msec_program = grep { $_ && m/$diff/g } chomp_(cat_($msec_conf)); if (scalar(@progs_orig_file)) {#test if is to remove or to add acl #clean config file of the removed programs foreach $element (@progs_orig_file){ my $val = $element; substInFile { s|$element.*\n||; } $perms_orig; $val =~ s/\t(.*)\s*//; $element =~ s/^(\d+)\t//; if ($val) { #write back in the msec file and set original file permissions #`unprotect $diff --remove`; remove_acl($dansguardian_protected_program_list, $diff); subst_config_line($msec_conf,"$element\n"); restore_permissions($element); } else { #only make the permissions wright #`unprotect $diff --remove`; remove_acl($dansguardian_protected_program_list, $diff); clean_config_line($msec_conf,"$diff"); restore_permissions($element); } } } else { if (scalar(@msec_program)){ output_p($perms_orig, @orig_file, "1\t".$_."\n") foreach @msec_program; #add file to msec and set acls } else { my $mode = (stat($diff))[2] & 07777; #"%04o" important to make 0755 to chmod ou chown $mode = sprintf "%lo", $mode; my $uid = (stat($diff))[4]; my $gid = (stat($diff))[5]; my $usrname = getpwuid($uid); my $gname = getgrgid($gid); my $to_add = "0\t$diff\t$usrname.$gname\t$mode\n"; #keep the permissons safe make the way to do that output_p($perms_orig, @orig_file, $to_add); } set_permissions($diff, grep {$_ && m/$diff/g} @act_list); } } } #this is just the case to reactivate the parental control #`unprotect $_ --remove` foreach @intersection; remove_acl($dansguardian_protected_program_list, $_) foreach @intersection; foreach my $intersec (@intersection){ set_permissions($intersec, grep {$_ && m/$intersec/g} @orig_list); } } else { my @original_list = list_get_entries(@url_lists[2]->{list}); for (@original_list){ s/\s(.*)//; } #restore the original file permissions `setfacl -b $_` foreach @original_list; foreach my $list (@original_list) { my @progs_orig_file = grep { $_ && m/$list/g } chomp_(cat_($perms_orig)); #test if program is in msec if (scalar(@progs_orig_file)) { #clean config file of the removed programs foreach my $element (@progs_orig_file){ my $val = $element; $val =~ s/\t(.*)\s*//; $element =~ s/^(\d+)\t//; if ($val) { #write back in the msec file and set original file permissions subst_config_line($msec_conf,"$element\n"); restore_permissions($element); } else { #only make the permissions wright clean_config_line($msec_conf,"$list"); restore_permissions($element); } } } } } }