]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - html/cgi-bin/urlfilter.cgi
suricata: Change midstream policy to "pass-flow"
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / urlfilter.cgi
index 33e52ae13dac10a4b32516cbddeaf685ced2548d..1ced06e26bdd546b7d3ec738e85bb3e926f4dc28 100644 (file)
@@ -1,13 +1,23 @@
 #!/usr/bin/perl
-#
-# SmoothWall CGIs
-#
-# This code is distributed under the terms of the GPL
-#
-# (c) written from scratch
-#
-# $Id: urlfilter.cgi,v 1.7 2006/05/08 00:00:00 marco Exp $
-#
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2005-2010  IPFire Team                                        #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
 
 use strict;
 
@@ -22,6 +32,7 @@ require '/var/ipfire/general-functions.pl';
 require "${General::swroot}/lang.pl";
 require "${General::swroot}/header.pl";
 
+my $http_port='81';
 my %netsettings=();
 my %mainsettings=();
 my %proxysettings=();
@@ -48,15 +59,13 @@ my $tcfile = "${General::swroot}/urlfilter/timeconst";
 my $uqfile = "${General::swroot}/urlfilter/userquota";
 my $dbdir = "${General::swroot}/urlfilter/blacklists";
 my $editdir = "${General::swroot}/urlfilter/editor";
-my $repository = "/home/httpd/html/repository";
+my $templatedir = "/srv/web/ipfire/html/redirect-templates";
+my $repository = "/var/urlrepo";
 my $hintcolour = '#FFFFCC';
 
 my $sourceurlfile = "${General::swroot}/urlfilter/autoupdate/autoupdate.urls";
 my $updconffile = "${General::swroot}/urlfilter/autoupdate/autoupdate.conf";
 my $updflagfile = "${General::swroot}/urlfilter/blacklists/.autoupdate.last";
-my $upd_cron_dly = "${General::swroot}/urlfilter/autoupdate/cron.daily";
-my $upd_cron_wly = "${General::swroot}/urlfilter/autoupdate/cron.weekly";
-my $upd_cron_mly = "${General::swroot}/urlfilter/autoupdate/cron.monthly";
 
 my $errormessage='';
 my $updatemessage='';
@@ -74,6 +83,7 @@ my @filtergroups=();
 my @tclist=();
 my @uqlist=();
 my @source_urllist=();
+my @clients=();
 my @temp=();
 
 my $lastslashpos=0;
@@ -85,9 +95,9 @@ my $ldesc='';
 my $gdesc='';
 
 if (! -d $dbdir) { mkdir("$dbdir"); }
-if (! -e $tcfile) { system("touch $tcfile"); }
-if (! -e $uqfile) { system("touch $uqfile"); }
-if (! -e $sourceurlfile) { system("touch $sourceurlfile"); }
+if (! -e $tcfile) { &General::system("touch", "$tcfile"); }
+if (! -e $uqfile) { &General::system("touch", "$uqfile"); }
+if (! -e $sourceurlfile) { &General::system("touch", "$sourceurlfile"); }
 
 &General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
 &General::readhash("${General::swroot}/main/settings", \%mainsettings);
@@ -128,12 +138,11 @@ $filtersettings{'BLOCK_IP_ADDR'} = 'off';
 $filtersettings{'BLOCK_ALL'} = 'off';
 $filtersettings{'ENABLE_EMPTY_ADS'} = 'off';
 $filtersettings{'ENABLE_GLOBAL_WHITELIST'} = 'off';
-$filtersettings{'ENABLE_SAFESEARCH'} = 'off';
 $filtersettings{'ENABLE_LOG'} = 'off';
 $filtersettings{'ENABLE_USERNAME_LOG'} = 'off';
 $filtersettings{'ENABLE_CATEGORY_LOG'} = 'off';
-$filtersettings{'CHILDREN'} = '5';
 $filtersettings{'ENABLE_AUTOUPDATE'} = 'off';
+$filtersettings{'REDIRECT_TEMPLATE'} = 'legacy';
 
 $filtersettings{'ACTION'} = '';
 $filtersettings{'VALID'} = '';
@@ -147,16 +156,28 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
     ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter save and restart'}) ||
     ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter upload file'}) ||
     ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter remove file'}) ||
-    ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter upload background'}) ||
     ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter upload blacklist'}) ||
     ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter backup'}) ||
     ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter restore'}))
-{ 
-       if (!($filtersettings{'CHILDREN'} =~ /^\d+$/) || ($filtersettings{'CHILDREN'} < 1))
+{
+
+       @clients = split(/\n/,$filtersettings{'UNFILTERED_CLIENTS'});
+       foreach (@clients)
+       {
+               s/^\s+//g; s/\s+$//g; s/\s+-\s+/-/g; s/\s+/ /g; s/\n//g;
+               if (/.*-.*-.*/) { $errormessage = $Lang::tr{'urlfilter invalid ip or mask error'}; }
+               @temp = split(/-/);
+               foreach (@temp) { unless ((&General::validipormask($_)) || (&General::validipandmask($_))) { $errormessage = $Lang::tr{'urlfilter invalid ip or mask error'}; } }
+       }
+       @clients = split(/\n/,$filtersettings{'BANNED_CLIENTS'});
+       foreach (@clients)
        {
-               $errormessage = $Lang::tr{'urlfilter invalid num of children'};
-               goto ERROR;
+               s/^\s+//g; s/\s+$//g; s/\s+-\s+/-/g; s/\s+/ /g; s/\n//g;
+               if (/.*-.*-.*/) { $errormessage = $Lang::tr{'urlfilter invalid ip or mask error'}; }
+               @temp = split(/-/);
+               foreach (@temp) { unless ((&General::validipormask($_)) || (&General::validipandmask($_))) { $errormessage = $Lang::tr{'urlfilter invalid ip or mask error'}; } }
        }
+       if ($errormessage) { goto ERROR; }
 
        if ((!($filtersettings{'REDIRECT_PAGE'} eq '')) && (!($filtersettings{'REDIRECT_PAGE'} =~ /^https?:\/\//)))
        {
@@ -186,18 +207,7 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
                }
 
        }
-       
-       if ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter upload background'})
-       {
-               &Header::getcgihash(\%filtersettings, {'wantfile' => 1, 'filevar' => 'BACKGROUND'});
 
-               if (copy($filtersettings{'BACKGROUND'}, "/home/httpd/html/images/urlfilter/background.jpg") != 1)
-               {
-                       $errormessage = $!;
-                       goto ERROR;
-               }
-       }
-       
        if ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter upload blacklist'})
        {
                &Header::getcgihash(\%filtersettings, {'wantfile' => 1, 'filevar' => 'UPDATEFILE'});
@@ -213,25 +223,31 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
                        $errormessage = $!;
                        goto ERROR;
                }
-               
+
                if (!(-d "${General::swroot}/urlfilter/update")) { mkdir("${General::swroot}/urlfilter/update"); }
 
-               my $exitcode = system("/bin/tar --no-same-owner -xzf ${General::swroot}/urlfilter/blacklists.tar.gz -C ${General::swroot}/urlfilter/update");
-               
+               my $exitcode = &General::system("/bin/tar", "--no-same-owner", "-xzf", "${General::swroot}/urlfilter/blacklists.tar.gz", "-C", "${General::swroot}/urlfilter/update");
+
                if ($exitcode > 0)
                {
                        $errormessage = $Lang::tr{'urlfilter tar error'};
                } else {
 
+                       if (-d "${General::swroot}/urlfilter/update/BL")
+                       {
+                               &General::system("mv", "${General::swroot}/urlfilter/update/BL", "${General::swroot}/urlfilter/update/blacklists");
+                       }
+
                        if (-d "${General::swroot}/urlfilter/update/category")
                        {
-                               system("mv ${General::swroot}/urlfilter/update/category ${General::swroot}/urlfilter/update/blacklists");
+                               &General::system("mv", "${General::swroot}/urlfilter/update/category", "${General::swroot}/urlfilter/update/blacklists");
                        }
 
                        if (!(-d "${General::swroot}/urlfilter/update/blacklists"))
                        {
                                $errormessage = $Lang::tr{'urlfilter invalid content'};
                        } else {
+                               # XXX Uses globbing
                                system("cp -r ${General::swroot}/urlfilter/update/blacklists/* $dbdir");
 
                                &readblockcategories;
@@ -240,11 +256,11 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
                                &writeconfigfile;
 
                                $updatemessage = $Lang::tr{'urlfilter upload success'};
-                               system("${General::swroot}/urlfilter/bin/prebuild.pl &");
-                               system("logger -t installpackage[urlfilter] \"URL filter blacklist - Blacklist update from local source completed\"");
+                               &General::system_background("${General::swroot}/urlfilter/bin/prebuild.pl");
+                               &General::system("logger", "-t", "installpackage[urlfilter]", "URL filter blacklist - Blacklist update from local source completed");
                        }
                }
-               if (-d "${General::swroot}/urlfilter/update") { system("rm -rf ${General::swroot}/urlfilter/update"); }
+               if (-d "${General::swroot}/urlfilter/update") { &General::system("rm", "-rf", "${General::swroot}/urlfilter/update"); }
                if (-e "${General::swroot}/urlfilter/blacklists.tar.gz") { unlink("${General::swroot}/urlfilter/blacklists.tar.gz"); }
                if ($errormessage) { goto ERROR; }
        }
@@ -252,7 +268,7 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
        if ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter backup'})
        {
                $blistbackup = ($filtersettings{'ENABLE_FULLBACKUP'} eq 'on') ? "blacklists" : "blacklists/custom";
-               if (system("/bin/tar -C ${General::swroot}/urlfilter -czf ${General::swroot}/urlfilter/backup.tar.gz settings timeconst userquota autoupdate $blistbackup"))
+               if (&General::system("/bin/tar", "-C", "${General::swroot}/urlfilter", "-czf", "${General::swroot}/urlfilter/backup.tar.gz", "settings", "timeconst", "userquota", "autoupdate", "$blistbackup"))
                {
                        $errormessage = $Lang::tr{'urlfilter backup error'};
                        goto ERROR;
@@ -290,8 +306,8 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
                {
                        $errormessage = $!;
                }
-               
-               my $exitcode = system("/bin/tar --no-same-owner --preserve-permissions -xzf ${General::swroot}/urlfilter/backup.tar.gz -C ${General::swroot}/urlfilter/restore");
+
+               my $exitcode = &General::system("/bin/tar", "--no-same-owner", "--preserve-permissions", "-xzf", "${General::swroot}/urlfilter/backup.tar.gz", "-C", "${General::swroot}/urlfilter/restore");
                if ($exitcode > 0)
                {
                        $errormessage = $Lang::tr{'urlfilter tar error'};
@@ -300,6 +316,7 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
                        {
                                $errormessage = $Lang::tr{'urlfilter invalid restore file'};
                        } else {
+                               # XXX uses globbing
                                system("cp -rp ${General::swroot}/urlfilter/restore/* ${General::swroot}/urlfilter/");
                                &readblockcategories;
                                &readcustomlists;
@@ -310,7 +327,7 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
                }
 
                if (-e "${General::swroot}/urlfilter/backup.tar.gz") { unlink("${General::swroot}/urlfilter/backup.tar.gz"); }
-               if (-d "${General::swroot}/urlfilter/restore") { system("rm -rf ${General::swroot}/urlfilter/restore"); }
+               if (-d "${General::swroot}/urlfilter/restore") { &General::system("rm", "-rf", "${General::swroot}/urlfilter/restore"); }
                if ($errormessage) { goto ERROR; }
        }
 
@@ -322,7 +339,7 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
 
        if ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter save and restart'})
        {
-               if (!(-e "${General::swroot}/proxy/enable"))
+               if ((!(-e "${General::swroot}/proxy/enable")) && (!(-e "${General::swroot}/proxy/enable_blue")))
                {
                        $errormessage = $Lang::tr{'urlfilter web proxy service required'};
                        goto ERROR;
@@ -336,36 +353,8 @@ if (($filtersettings{'ACTION'} eq $Lang::tr{'save'}) ||
                $filtersettings{'VALID'} = 'yes';
                &savesettings;
 
-               system("chown -R nobody.nobody $dbdir");
-
-               if (-e "$dbdir/custom/allowed/domains.db") { unlink("$dbdir/custom/allowed/domains.db"); }
-               if (-e "$dbdir/custom/allowed/urls.db")    { unlink("$dbdir/custom/allowed/urls.db"); }
-               if (-e "$dbdir/custom/blocked/domains.db") { unlink("$dbdir/custom/blocked/domains.db"); }
-               if (-e "$dbdir/custom/blocked/urls.db")    { unlink("$dbdir/custom/blocked/urls.db"); }
-
-               foreach (<$dbdir/*>)
-               {
-                       if (-d $_){ system("chmod 644 $_/*"); }
-                       if (-d $_){ system("chmod 666 $_/*.db"); }
-               }
-               if (-d "$dbdir/custom/allowed")
-               {
-                       system("chmod 755 $dbdir/custom/allowed");
-                       system("chmod 644 $dbdir/custom/allowed/*");
-               }
-               if (-d "$dbdir/custom/blocked")
-               {
-                       system("chmod 755 $dbdir/custom/blocked");
-                       system("chmod 644 $dbdir/custom/blocked/*");
-               }
-
-               system('/usr/local/bin/restartsquid');
+               &General::system('/usr/local/bin/squidctrl', 'restart');
        }
-
-ERROR:
-
-       if ($errormessage) { $filtersettings{'VALID'} = 'no'; }
-
 }
 
 if ($tcsettings{'ACTION'} eq $Lang::tr{'urlfilter set time constraints'}) { $tcsettings{'TCMODE'} = 'on'}
@@ -396,6 +385,16 @@ if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang
 
        if (!$errormessage)
        {
+               # transform to pre1.8 client definitions
+               @clients = split(/\n/,$tcsettings{'SRC'});
+               undef $tcsettings{'SRC'};
+               foreach(@clients)
+               {
+                       s/^\s+//g; s/\s+$//g; s/\s+-\s+/-/g; s/\s+/ /g; s/\n//g;
+                       $tcsettings{'SRC'} .= "$_ ";
+               }
+               $tcsettings{'SRC'} =~ s/\s+$//;
+
                if ($tcsettings{'DST'} =~ /^any/) { $tcsettings{'DST'} = 'any'; }
                if ($tcsettings{'ENABLERULE'} eq 'on') { $tcsettings{'ACTIVE'} = $tcsettings{'ENABLERULE'}; } else { $tcsettings{'ACTIVE'} = 'off'}
 
@@ -430,6 +429,38 @@ if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang
        }
 }
 
+if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang::tr{'urlfilter copy rule'}) && (!$errormessage))
+{
+       $id = 0;
+       foreach $line (@tclist)
+       {
+               $id++;
+               if ($tcsettings{'ID'} eq $id)
+               {
+                       chomp($line);
+                       @temp = split(/\,/,$line);
+                       $tcsettings{'DEFINITION'} = $temp[0];
+                       $tcsettings{'MON'} = $temp[1];
+                       $tcsettings{'TUE'} = $temp[2];
+                       $tcsettings{'WED'} = $temp[3];
+                       $tcsettings{'THU'} = $temp[4];
+                       $tcsettings{'FRI'} = $temp[5];
+                       $tcsettings{'SAT'} = $temp[6];
+                       $tcsettings{'SUN'} = $temp[7];
+                       $tcsettings{'FROM_HOUR'} = $temp[8];
+                       $tcsettings{'FROM_MINUTE'} = $temp[9];
+                       $tcsettings{'TO_HOUR'} = $temp[10];
+                       $tcsettings{'TO_MINUTE'} = $temp[11];
+                       $tcsettings{'SRC'} = $temp[12];
+                       $tcsettings{'DST'} = $temp[13];
+                       $tcsettings{'ACCESS'} = $temp[14];
+                       $tcsettings{'ENABLERULE'} = $temp[15];
+                       $tcsettings{'COMMENT'} = $temp[16];
+               }
+       }
+       $tcsettings{'TCMODE'}='on';
+}
+
 if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang::tr{'remove'}))
 {
        $id = 0;
@@ -451,12 +482,12 @@ if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang
        {
                $errormessage = $Lang::tr{'urlfilter not enabled'};
        }
-       if (!(-e "${General::swroot}/proxy/enable"))
+       if ((!(-e "${General::swroot}/proxy/enable")) && (!(-e "${General::swroot}/proxy/enable_blue")))
        {
                $errormessage = $Lang::tr{'urlfilter web proxy service required'};
        }
 
-       if (!$errormessage) { system('/usr/local/bin/restartsquid'); }
+       if (!$errormessage) { &General::system('/usr/local/bin/squidctrl', 'restart'); }
        $tcsettings{'TCMODE'}='on';
 }
 
@@ -482,11 +513,6 @@ if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang
        $tcsettings{'TCMODE'}='on';
 }
 
-if (!$errormessage) {
-       $tcsettings{'ENABLERULE'}='on';
-       $tcsettings{'TO_HOUR'}='24';
-}
-
 if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang::tr{'edit'}) && (!$errormessage))
 {
        $id = 0;
@@ -519,6 +545,11 @@ if (($tcsettings{'MODE'} eq 'TIMECONSTRAINT') && ($tcsettings{'ACTION'} eq $Lang
        $tcsettings{'TCMODE'}='on';
 }
 
+if ((!$errormessage) && (!($tcsettings{'ACTION'} eq $Lang::tr{'urlfilter copy rule'})) && (!($tcsettings{'ACTION'} eq $Lang::tr{'edit'}))) {
+       $tcsettings{'ENABLERULE'}='on';
+       $tcsettings{'TO_HOUR'}='24';
+}
+
 if ($uqsettings{'ACTION'} eq $Lang::tr{'urlfilter set user quota'}) { $uqsettings{'UQMODE'} = 'on'}
 
 if (($uqsettings{'MODE'} eq 'USERQUOTA') && ($uqsettings{'ACTION'} eq $Lang::tr{'add'}))
@@ -654,12 +685,12 @@ if (($uqsettings{'MODE'} eq 'USERQUOTA') && ($uqsettings{'ACTION'} eq $Lang::tr{
        {
                $errormessage = $Lang::tr{'urlfilter not enabled'};
        }
-       if (!(-e "${General::swroot}/proxy/enable"))
+       if ((!(-e "${General::swroot}/proxy/enable")) && (!(-e "${General::swroot}/proxy/enable_blue")))
        {
                $errormessage = $Lang::tr{'urlfilter web proxy service required'};
        }
 
-       if (!$errormessage) { system('/usr/local/bin/restartsquid'); }
+       if (!$errormessage) { &General::system('/usr/local/bin/squidctrl', 'restart'); }
        $uqsettings{'UQMODE'}='on';
 }
 
@@ -742,8 +773,8 @@ if (($besettings{'ACTION'} eq $Lang::tr{'urlfilter import blacklist'}) && ($bese
                {
                        $errormessage = $!;
                } else {
-               
-                       my $exitcode = system("/bin/tar --no-same-owner --preserve-permissions -xzf $editdir/blacklist.tar.gz -C $editdir");
+
+                       my $exitcode = &General::system("/bin/tar", "--no-same-owner", "--preserve-permissions", "-xzf", "$editdir/blacklist.tar.gz", "-C", "$editdir");
                        if ($exitcode > 0)
                        {
                                $errormessage = $Lang::tr{'urlfilter tar error'};
@@ -790,7 +821,7 @@ if (($besettings{'ACTION'} eq $Lang::tr{'urlfilter import blacklist'}) && ($bese
                                }
                        }
 
-               if (-d $editdir) { system("rm -rf $editdir"); }
+               if (-d $editdir) { &General::system("rm", "-rf", "$editdir"); }
 
                }
        }
@@ -824,7 +855,7 @@ if (($besettings{'ACTION'} eq $Lang::tr{'urlfilter export blacklist'}) && ($bese
                print FILE "$besettings{'BE_EXPRESSIONS'}\n";
                close FILE;
 
-               if (system("/bin/tar -C $editdir -czf $editdir/$besettings{'BE_NAME'}.tar.gz blacklists"))
+               if (&General::system("/bin/tar", "-C", "$editdir", "-czf", "$editdir/$besettings{'BE_NAME'}.tar.gz", "blacklists"))
                {
                        $errormessage = $Lang::tr{'urlfilter export error'};
                }
@@ -840,7 +871,7 @@ if (($besettings{'ACTION'} eq $Lang::tr{'urlfilter export blacklist'}) && ($bese
                        while (<FILE>) { print; }
                        close (FILE);
 
-                       if (-d $editdir) { system("rm -rf $editdir"); }
+                       if (-d $editdir) { &General::system("rm", "-rf", "$editdir"); }
                        exit;
                }
        } else {
@@ -904,8 +935,10 @@ if (($besettings{'ACTION'} eq $Lang::tr{'urlfilter install blacklist'}) && ($bes
                print FILE "}\n";
                close FILE;
 
+               # XXX uses globbing
                system("rm -f $dbdir/$besettings{'BE_NAME'}/*.db");
-               system("/usr/sbin/squidGuard -c $editdir/install.conf -C all");
+               &General::system("/usr/bin/squidGuard", "-c", "$editdir/install.conf", "-C", "all");
+               # XXX uses globbing
                system("chmod a+w $dbdir/$besettings{'BE_NAME'}/*.db");
 
                &readblockcategories;
@@ -913,9 +946,9 @@ if (($besettings{'ACTION'} eq $Lang::tr{'urlfilter install blacklist'}) && ($bes
 
                &writeconfigfile;
 
-               system('/usr/local/bin/restartsquid') unless ($besettings{'NORESTART'} eq 'on');
+               &General::system('/usr/local/bin/squidctrl', 'restart') unless ($besettings{'NORESTART'} eq 'on');
 
-               if (-d $editdir) { system("rm -rf $editdir"); }
+               if (-d $editdir) { &General::system("rm", "-rf", "$editdir"); }
        } else {
                $errormessage = $Lang::tr{'urlfilter category data error'};
        }
@@ -934,29 +967,25 @@ if ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter save schedule'})
                print FILE "CUSTOM_UPDATE_URL=$filtersettings{'CUSTOM_UPDATE_URL'}\n";
                close FILE;
 
-               if (-e $upd_cron_dly) { unlink($upd_cron_dly); }
-               if (-e $upd_cron_wly) { unlink($upd_cron_wly); }
-               if (-e $upd_cron_mly) { unlink($upd_cron_mly); }
 
                if (($filtersettings{'ENABLE_AUTOUPDATE'} eq 'on') && ($filtersettings{'UPDATE_SCHEDULE'} eq 'daily'))
                {
-                       symlink("../bin/autoupdate.pl",$upd_cron_dly)
-               } else {
-                       symlink("/bin/false",$upd_cron_dly)
+                       &General::system('/usr/local/bin/urlfilterctrl', 'cron', 'daily');
                }
 
                if (($filtersettings{'ENABLE_AUTOUPDATE'} eq 'on') && ($filtersettings{'UPDATE_SCHEDULE'} eq 'weekly'))
                {
-                       symlink("../bin/autoupdate.pl",$upd_cron_wly)
-               } else {
-                       symlink("/bin/false",$upd_cron_wly)
+                       &General::system('/usr/local/bin/urlfilterctrl', 'cron', 'weekly');
                }
 
                if (($filtersettings{'ENABLE_AUTOUPDATE'} eq 'on') && ($filtersettings{'UPDATE_SCHEDULE'} eq 'monthly'))
                {
-                       symlink("../bin/autoupdate.pl",$upd_cron_mly)
-               } else {
-                       symlink("/bin/false",$upd_cron_mly)
+                       &General::system('/usr/local/bin/urlfilterctrl', 'cron', 'monthly');
+               }
+               
+               if ($filtersettings{'ENABLE_AUTOUPDATE'} eq 'off')
+               {
+                       &General::system('/usr/local/bin/urlfilterctrl', 'cron', 'remove');
                }
        }
 }
@@ -969,10 +998,10 @@ if ($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter update now'})
                {
                        $errormessage = $Lang::tr{'urlfilter custom url required'};
                } else {
-                       system("${General::swroot}/urlfilter/bin/autoupdate.pl $filtersettings{'CUSTOM_UPDATE_URL'} &");
+                       &General::system_background("${General::swroot}/urlfilter/bin/autoupdate.pl", "$filtersettings{'CUSTOM_UPDATE_URL'}");
                }
        } else {
-               system("${General::swroot}/urlfilter/bin/autoupdate.pl $filtersettings{'UPDATE_SOURCE'} &");
+               &General::system_background("${General::swroot}/urlfilter/bin/autoupdate.pl", "$filtersettings{'UPDATE_SOURCE'}");
        }
 }
 
@@ -981,6 +1010,10 @@ if (-e "${General::swroot}/urlfilter/settings") { &General::readhash("${General:
 
 &readcustomlists;
 
+ERROR:
+
+if ($errormessage) { $filtersettings{'VALID'} = 'no'; }
+
 $checked{'ENABLE_CUSTOM_BLACKLIST'}{'off'} = '';
 $checked{'ENABLE_CUSTOM_BLACKLIST'}{'on'} = '';
 $checked{'ENABLE_CUSTOM_BLACKLIST'}{$filtersettings{'ENABLE_CUSTOM_BLACKLIST'}} = "checked='checked'";
@@ -1032,9 +1065,6 @@ $checked{'ENABLE_EMPTY_ADS'}{$filtersettings{'ENABLE_EMPTY_ADS'}} = "checked='ch
 $checked{'ENABLE_GLOBAL_WHITELIST'}{'off'} = '';
 $checked{'ENABLE_GLOBAL_WHITELIST'}{'on'} = '';
 $checked{'ENABLE_GLOBAL_WHITELIST'}{$filtersettings{'ENABLE_GLOBAL_WHITELIST'}} = "checked='checked'";
-$checked{'ENABLE_SAFESEARCH'}{'off'} = '';
-$checked{'ENABLE_SAFESEARCH'}{'on'} = '';
-$checked{'ENABLE_SAFESEARCH'}{$filtersettings{'ENABLE_SAFESEARCH'}} = "checked='checked'";
 $checked{'ENABLE_LOG'}{'off'} = '';
 $checked{'ENABLE_LOG'}{'on'} = '';
 $checked{'ENABLE_LOG'}{$filtersettings{'ENABLE_LOG'}} = "checked='checked'";
@@ -1051,6 +1081,8 @@ foreach $category (@filtergroups) {
        $checked{$category}{$filtersettings{$category}} = "checked='checked'";
 }
 
+$selected{'REDIRECT_TEMPLATE'}{$filtersettings{'REDIRECT_TEMPLATE'}} = "selected='selected'";
+
 $selected{'DEFINITION'}{$tcsettings{'DEFINITION'}} = "selected='selected'";
 $selected{'FROM_HOUR'}{$tcsettings{'FROM_HOUR'}} = "selected='selected'";
 $selected{'FROM_MINUTE'}{$tcsettings{'FROM_MINUTE'}} = "selected='selected'";
@@ -1143,7 +1175,7 @@ if (!($filtersettings{'ACTION'} eq $Lang::tr{'urlfilter manage repository'})) {
 
 print "<form method='post' action='$ENV{'SCRIPT_NAME'}' enctype='multipart/form-data'>\n";
 
-&Header::openbox('100%', 'left', "$Lang::tr{'urlfilter filter settings'}:");
+&Header::openbox('100%', 'left', "$Lang::tr{'urlfilter filter settings'}");
 print <<END
 <table width='100%'>
 <tr>
@@ -1187,8 +1219,12 @@ print <<END
         <td>&nbsp;</td>
 </tr>
 <tr>
-       <td colspan='2'>$Lang::tr{'urlfilter blocked domains'}&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td colspan='2'>$Lang::tr{'urlfilter blocked urls'}&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td colspan='2'>$Lang::tr{'urlfilter blocked domains'}</td>
+       <td colspan='2'>$Lang::tr{'urlfilter blocked urls'}</td>
+</tr>
+<tr>
+       <td colspan='2'>$Lang::tr{'urlfilter example'}</td>
+       <td colspan='2'>$Lang::tr{'urlfilter example ads'}</td>
 </tr>
 <tr>
        <td colspan='2' width='50%'><textarea name='CUSTOM_BLACK_DOMAINS' cols='32' rows='6' wrap='off'>
@@ -1226,8 +1262,12 @@ print <<END
         <td>&nbsp;</td>
 </tr>
 <tr>
-       <td colspan='2'>$Lang::tr{'urlfilter allowed domains'}&nbsp;<img src='/blob.gif' alt='*' /></td>
-       <td colspan='2'>$Lang::tr{'urlfilter allowed urls'}&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td colspan='2'>$Lang::tr{'urlfilter allowed domains'}</td>
+       <td colspan='2'>$Lang::tr{'urlfilter allowed urls'}</td>
+</tr>
+<tr>
+       <td colspan='2'>$Lang::tr{'urlfilter example'}</td>
+       <td colspan='2'>$Lang::tr{'urlfilter example ads'}</td>
 </tr>
 <tr>
        <td colspan='2' width='50%'><textarea name='CUSTOM_WHITE_DOMAINS' cols='32' rows='6' wrap='off'>
@@ -1262,7 +1302,7 @@ print <<END
         <td colspan='4'><b>$Lang::tr{'urlfilter custom expression list'}</b></td>
 </tr>
 <tr>
-       <td colspan='4'>$Lang::tr{'urlfilter blocked expressions'}&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td colspan='4'>$Lang::tr{'urlfilter blocked expressions'}</td>
 </tr>
 <tr>
        <td colspan='4'><textarea name='CUSTOM_EXPRESSIONS' cols='70' rows='3' wrap='off'>
@@ -1325,10 +1365,46 @@ print <<END
         <td>&nbsp;</td>
 </tr>
 <tr>
-        <td class='base'>$Lang::tr{'urlfilter unfiltered clients'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
-        <td><input type='text' name='UNFILTERED_CLIENTS' value='$filtersettings{'UNFILTERED_CLIENTS'}' size='30' /></td>
-        <td class='base'>$Lang::tr{'urlfilter banned clients'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
-        <td><input type='text' name='BANNED_CLIENTS' value='$filtersettings{'BANNED_CLIENTS'}' size='30' /></td>
+       <td colspan='2'>$Lang::tr{'urlfilter unfiltered clients'}</td>
+       <td colspan='2'>$Lang::tr{'urlfilter banned clients'}</td>
+</tr>
+<tr>
+       <td colspan='2' width='50%'><textarea name='UNFILTERED_CLIENTS' cols='32' rows='6' wrap='off'>
+END
+;
+
+# transform from pre1.8 client definitions
+$filtersettings{'UNFILTERED_CLIENTS'} =~ s/^\s+//g;
+$filtersettings{'UNFILTERED_CLIENTS'} =~ s/\s+$//g;
+$filtersettings{'UNFILTERED_CLIENTS'} =~ s/\s+-\s+/-/g;
+$filtersettings{'UNFILTERED_CLIENTS'} =~ s/\s+/ /g;
+
+@clients = split(/ /,$filtersettings{'UNFILTERED_CLIENTS'});
+undef $filtersettings{'UNFILTERED_CLIENTS'};
+foreach (@clients) { $filtersettings{'UNFILTERED_CLIENTS'} .= "$_\n"; }
+
+print $filtersettings{'UNFILTERED_CLIENTS'};
+
+print <<END
+</textarea></td>
+       <td colspan='2' width='50%'><textarea name='BANNED_CLIENTS' cols='32' rows='6' wrap='off'>
+END
+;
+
+# transform from pre1.8 client definitions
+$filtersettings{'BANNED_CLIENTS'} =~ s/^\s+//g;
+$filtersettings{'BANNED_CLIENTS'} =~ s/\s+$//g;
+$filtersettings{'BANNED_CLIENTS'} =~ s/\s+-\s+/-/g;
+$filtersettings{'BANNED_CLIENTS'} =~ s/\s+/ /g;
+
+@clients = split(/ /,$filtersettings{'BANNED_CLIENTS'});
+undef $filtersettings{'BANNED_CLIENTS'};
+foreach (@clients) { $filtersettings{'BANNED_CLIENTS'} .= "$_\n"; }
+
+print $filtersettings{'BANNED_CLIENTS'};
+
+print <<END
+</textarea></td>
 </tr>
 </table>
 <hr size='1'>
@@ -1348,47 +1424,48 @@ print <<END
 <tr>
         <td colspan='4'><b>$Lang::tr{'urlfilter block settings'}</b></td>
 </tr>
+<tr>
+       <td width='25%' class='base'>$Lang::tr{'urlfilter redirect template'}</td>
+       <td width='75%' colspan='2'>
+               <select name='REDIRECT_TEMPLATE'>
+END
+;
+
+       foreach (<$templatedir/*>) {
+               if ((-d "$_") && (-e "$_/template.html")) {
+                       my $template = substr($_,rindex($_,"/")+1);
+                       print "<option value='$template' $selected{'REDIRECT_TEMPLATE'}{$template}>$template</option>\n";
+               }
+       }
+
+print <<END
+               </select>
+       </td>
+</tr>
 <tr>
        <td width='25%' class='base'>$Lang::tr{'urlfilter show category'}:</td>
        <td width='12%'><input type='checkbox' name='SHOW_CATEGORY' $checked{'SHOW_CATEGORY'}{'on'} /></td>
-       <td width='25%' class='base'>$Lang::tr{'urlfilter redirectpage'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td width='25%' class='base'>$Lang::tr{'urlfilter redirectpage'}:</td>
        <td><input type='text' name='REDIRECT_PAGE' value='$filtersettings{'REDIRECT_PAGE'}' size='40' /></td>
 </tr>
 <tr>
        <td class='base'>$Lang::tr{'urlfilter show url'}:</td>
        <td><input type='checkbox' name='SHOW_URL' $checked{'SHOW_URL'}{'on'} /></td>
-       <td class='base'>$Lang::tr{'urlfilter msg text 1'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td class='base'>$Lang::tr{'urlfilter msg text 1'}:</td>
        <td><input type='text' name='MSG_TEXT_1' value='$filtersettings{'MSG_TEXT_1'}' size='40' /></td>
 </tr>
 <tr>
        <td class='base'>$Lang::tr{'urlfilter show ip'}:</td>
        <td><input type='checkbox' name='SHOW_IP' $checked{'SHOW_IP'}{'on'} /></td>
-       <td class='base'>$Lang::tr{'urlfilter msg text 2'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td class='base'>$Lang::tr{'urlfilter msg text 2'}:</td>
        <td><input type='text' name='MSG_TEXT_2' value='$filtersettings{'MSG_TEXT_2'}' size='40' /></td>
 </tr>
 <tr>
        <td class='base'>$Lang::tr{'urlfilter show dnserror'}:</td>
        <td><input type='checkbox' name='ENABLE_DNSERROR' $checked{'ENABLE_DNSERROR'}{'on'} /></td>
-       <td class='base'>$Lang::tr{'urlfilter msg text 3'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
+       <td class='base'>$Lang::tr{'urlfilter msg text 3'}:</td>
        <td><input type='text' name='MSG_TEXT_3' value='$filtersettings{'MSG_TEXT_3'}' size='40' /></td>
 </tr>
-<tr>
-       <td class='base'>$Lang::tr{'urlfilter enable jpeg'}:</td>
-       <td><input type='checkbox' name='ENABLE_JPEG' $checked{'ENABLE_JPEG'}{'on'} /></td>
-       <td>&nbsp;</td>
-       <td>&nbsp;</td>
-</tr>
-</table>
-<table width='100%'>
-<tr>
-       <td class='base'><b>$Lang::tr{'urlfilter background image'}</b></td>
-</tr>
-<tr>
-       <td><br>$Lang::tr{'urlfilter background text'}:</td>
-</tr>
-<tr>
-       <td><input type='file' name='BACKGROUND' size='40' /> &nbsp; <input type='submit' name='ACTION' value='$Lang::tr{'urlfilter upload background'}' /></td>
-</tr>
 </table>
 <hr size='1'>
 <table width='100%'>
@@ -1401,23 +1478,17 @@ print <<END
        <td width='25%' class='base'>$Lang::tr{'urlfilter enable log'}:</td>
        <td><input type='checkbox' name='ENABLE_LOG' $checked{'ENABLE_LOG'}{'on'} /></td>
 </tr>
-<tr>
-       <td class='base'>$Lang::tr{'urlfilter safesearch'}:</td>
-       <td><input type='checkbox' name='ENABLE_SAFESEARCH' $checked{'ENABLE_SAFESEARCH'}{'on'} /></td>
-       <td class='base'>$Lang::tr{'urlfilter username log'}:</td>
-       <td><input type='checkbox' name='ENABLE_USERNAME_LOG' $checked{'ENABLE_USERNAME_LOG'}{'on'} /></td>
-</tr>
 <tr>
        <td class='base'>$Lang::tr{'urlfilter empty ads'}:</td>
        <td><input type='checkbox' name='ENABLE_EMPTY_ADS' $checked{'ENABLE_EMPTY_ADS'}{'on'} /></td>
-       <td class='base'>$Lang::tr{'urlfilter category log'}:</td>
-       <td><input type='checkbox' name='ENABLE_CATEGORY_LOG' $checked{'ENABLE_CATEGORY_LOG'}{'on'} /></td>
+       <td class='base'>$Lang::tr{'urlfilter username log'}:</td>
+       <td><input type='checkbox' name='ENABLE_USERNAME_LOG' $checked{'ENABLE_USERNAME_LOG'}{'on'} /></td>
 </tr>
 <tr>
        <td class='base'>$Lang::tr{'urlfilter block ip'}:</td>
        <td><input type='checkbox' name='BLOCK_IP_ADDR' $checked{'BLOCK_IP_ADDR'}{'on'} /></td>
-       <td class='base'>$Lang::tr{'urlfilter children'}:</td>
-       <td><input type='text' name='CHILDREN' value='$filtersettings{'CHILDREN'}' size='5' /></td>
+       <td class='base'>$Lang::tr{'urlfilter category log'}:</td>
+       <td><input type='checkbox' name='ENABLE_CATEGORY_LOG' $checked{'ENABLE_CATEGORY_LOG'}{'on'} /></td>
 </tr>
 <tr>
        <td class='base'>$Lang::tr{'urlfilter block all'}:</td>
@@ -1429,12 +1500,8 @@ print <<END
 <hr size='1'>
 <table width='100%'>
 <tr>
-       <td>
-       <img src='/blob.gif' align='top' alt='*' />&nbsp;
-       <font class='base'>$Lang::tr{'this field may be blank'}</font>
-       </td>
-       <td align='right'>&nbsp;
-</td>
+       <td><img src='/blob.gif' align='top' alt='*' />&nbsp;<font class='base'>$Lang::tr{'required field'}</font></td>
+       <td align='right'>&nbsp;</td>
 </tr>
 </table>
 <table width='100%'>
@@ -1454,7 +1521,7 @@ print "</form>\n";
 
 print "<form method='post' action='$ENV{'SCRIPT_NAME'}' enctype='multipart/form-data'>\n";
 
-&Header::openbox('100%', 'left', "$Lang::tr{'urlfilter maintenance'}:");
+&Header::openbox('100%', 'left', "$Lang::tr{'urlfilter maintenance'}");
 
 print <<END
 <table width='100%'>
@@ -1810,18 +1877,36 @@ print <<END
 
 <table width='100%'>
        <tr>
-               <td width='5%'>$Lang::tr{'urlfilter source'}</td>
+               <td width='5%'>$Lang::tr{'urlfilter source'}&nbsp;<img src='/blob.gif' alt='*' /></td>
                <td width='1%'>&nbsp;&nbsp;</td>
-               <td width='5%'>$Lang::tr{'urlfilter dst'}&nbsp;<img src='/blob.gif' alt='*'><img src='/blob.gif' alt='*'></td>
+               <td width='5%'>$Lang::tr{'urlfilter dst'}&nbsp;<img src='/blob.gif' alt='*' /></td>
                <td width='1%'>&nbsp;&nbsp;</td>
                <td width='5%'>$Lang::tr{'urlfilter access'}</td>
                <td>&nbsp;</td>
        </tr>
        <tr>
-               <td valign='top'><input type='text' name='SRC' value='$tcsettings{'SRC'}' size='32' /></td>
+        <td rowspan='2'><textarea name='SRC' cols='28' rows='5' wrap='off'>
+END
+;
+
+# transform from pre1.8 client definitions
+$tcsettings{'SRC'} =~ s/^\s+//g;
+$tcsettings{'SRC'} =~ s/\s+$//g;
+$tcsettings{'SRC'} =~ s/\s+-\s+/-/g;
+$tcsettings{'SRC'} =~ s/\s+/ /g;
+
+@clients = split(/ /,$tcsettings{'SRC'});
+undef $tcsettings{'SRC'};
+foreach (@clients) { $tcsettings{'SRC'} .= "$_\n"; }
+
+print $tcsettings{'SRC'};
+
+print <<END
+</textarea></td>
+
                <td>&nbsp;</td>
-               <td class='base' rowspan='3' valign='top'>
-               <select name='DST' size='4' multiple>
+               <td class='base' rowspan='2' valign='top'>
+               <select name='DST' size='6' multiple>
                <option value='any' $selected{'DST'}{'any'} = "selected='selected'">$Lang::tr{'urlfilter category all'}</option>
                <option value='in-addr' $selected{'DST'}{'in-addr'} = "selected='selected'">in-addr</option>
 END
@@ -1849,7 +1934,14 @@ print <<END
                <td>&nbsp;</td>
        </tr>
        <tr>
-               <td>$Lang::tr{'remark'}&nbsp;<img src='/blob.gif' alt='*'></td>
+               <td>&nbsp;</td>
+               <td>&nbsp;</td>
+               <td>&nbsp;</td>
+               <td>&nbsp;</td>
+       </tr>
+       <tr>
+               <td>$Lang::tr{'remark'}</td>
+               <td>&nbsp;</td>
                <td>&nbsp;</td>
                <td>&nbsp;</td>
                <td>&nbsp;</td>
@@ -1861,6 +1953,7 @@ print <<END
                <td>&nbsp;</td>
                <td>&nbsp;</td>
                <td>&nbsp;</td>
+               <td>&nbsp;</td>
        </tr>
 </table>
 
@@ -1886,10 +1979,10 @@ print <<END
 <table width='100%'>
        <tr>
                <td width='1%' align='right'> <img src='/blob.gif' align='top' alt='*' />&nbsp;</td>
-               <td><font class='base'>$Lang::tr{'this field may be blank'}</font></td>
+               <td><font class='base'>$Lang::tr{'required field'}</font></td>
        </tr>
        <tr>
-               <td width='1%' align='right'><img src='/blob.gif' align='top' alt='*' /><img src='/blob.gif' align='top' alt='*' />&nbsp;</td>
+               <td width='1%' align='right'>&nbsp;</td>
                <td><font class='base'>$Lang::tr{'urlfilter select multi'}</font></td>
        </tr>
 </table>
@@ -1913,7 +2006,7 @@ print <<END
                <td width='10%' class='boldbase' align='center'><b>$Lang::tr{'urlfilter time space'}</b></td>
                <td width='15%' class='boldbase' align='center'><b>$Lang::tr{'urlfilter src'}</b></td>
                <td width='5%' class='boldbase' align='center'><b>$Lang::tr{'urlfilter dst'}</b></td>
-               <td width='10%' class='boldbase' colspan='4' align='center'>&nbsp;</td>
+               <td width='10%' class='boldbase' colspan='5' align='center'>&nbsp;</td>
        </tr>
 END
 ;
@@ -1982,6 +2075,15 @@ print <<END
 
                <td align='center'>
                <form method='post' name='frmc$id' action='$ENV{'SCRIPT_NAME'}'>
+               <input type='image' name='$Lang::tr{'urlfilter copy rule'}' src='/images/urlfilter/copy.gif' title='$Lang::tr{'urlfilter copy rule'}' alt='$Lang::tr{'urlfilter copy rule'}' />
+               <input type='hidden' name='MODE' value='TIMECONSTRAINT' />
+               <input type='hidden' name='ID' value='$id' />
+               <input type='hidden' name='ACTION' value='$Lang::tr{'urlfilter copy rule'}' />
+               </form>
+               </td>
+
+               <td align='center'>
+               <form method='post' name='frmd$id' action='$ENV{'SCRIPT_NAME'}'>
                <input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' title='$Lang::tr{'remove'}' alt='$Lang::tr{'remove'}' />
                <input type='hidden' name='MODE' value='TIMECONSTRAINT' />
                <input type='hidden' name='ID' value='$id' />
@@ -2001,7 +2103,7 @@ END
 print <<END
                <td align='center' colspan='4'>$temp[16]
                </td>
-               <td align='center' colspan='4'>
+               <td align='center' colspan='5'>
                </td>
        </tr>
 END
@@ -2027,6 +2129,8 @@ print <<END
                <td class='base'>$Lang::tr{'click to enable'}</td>
                <td>&nbsp; &nbsp; <img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
                <td class='base'>$Lang::tr{'edit'}</td>
+               <td>&nbsp; &nbsp; <img src='/images/urlfilter/copy.gif' alt='$Lang::tr{'urlfilter copy rule'}' /></td>
+               <td class='base'>$Lang::tr{'urlfilter copy rule'}</td>
                <td>&nbsp; &nbsp; <img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
                <td class='base'>$Lang::tr{'remove'}</td>
        </tr>
@@ -2061,7 +2165,7 @@ print <<END
        <td width='25%'></td> <td width='20%'> </td><td width='25%'> </td><td width='30%'></td>
 </tr>
 <tr>
-        <td class='base'>$Lang::tr{'urlfilter user time quota'}:</td>
+        <td class='base'>$Lang::tr{'urlfilter user time quota'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
         <td><input type='text' name='TIME_QUOTA' value='$uqsettings{'TIME_QUOTA'}' size='5' /></td>
        <td colspan='2' rowspan= '5' valign='top' class='base'>
                <table cellpadding='0' cellspacing='0'>
@@ -2069,7 +2173,7 @@ print <<END
                                <!-- intentionally left empty -->
                        </tr>
                        <tr>
-                       <td>$Lang::tr{'urlfilter assigned quota users'}:</td>
+                       <td>$Lang::tr{'urlfilter assigned quota users'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
                        </tr>
                        <tr>
                                <!-- intentionally left empty -->
@@ -2267,7 +2371,7 @@ print <<END
                <td class='base'><b>$Lang::tr{'urlfilter blacklist name'}</b></td>
 </tr>
 <tr>
-               <td class='base'>$Lang::tr{'urlfilter blacklist category name'}:</td>
+               <td class='base'>$Lang::tr{'urlfilter blacklist category name'}:&nbsp;<img src='/blob.gif' alt='*' /></td>
        <td><input type='text' name='BE_NAME' value='$besettings{'BE_NAME'}' size='12' /></td>
 </tr>
 </table>
@@ -2277,7 +2381,7 @@ print <<END
        <td width='25%'></td> <td width='20%'> </td><td width='25%'> </td><td width='20%'></td>
 </tr>
 <tr>
-               <td class='base' colspan='4'><b>$Lang::tr{'urlfilter edit domains urls expressions'}</b></td>
+               <td class='base' colspan='4'><b>$Lang::tr{'urlfilter edit domains urls expressions'}</b>&nbsp;<img src='/blob.gif' alt='*' /></td>
 </tr>
 <tr>
        <td colspan='2'>$Lang::tr{'urlfilter domains'}</td>
@@ -2408,6 +2512,26 @@ print "</form>\n";
 
 sub savesettings
 {
+       # transform to pre1.8 client definitions
+       @clients = split(/\n/,$filtersettings{'UNFILTERED_CLIENTS'});
+       undef $filtersettings{'UNFILTERED_CLIENTS'};
+       foreach(@clients)
+       {
+               s/^\s+//g; s/\s+$//g; s/\s+-\s+/-/g; s/\s+/ /g; s/\n//g;
+               $filtersettings{'UNFILTERED_CLIENTS'} .= "$_ ";
+       }
+       $filtersettings{'UNFILTERED_CLIENTS'} =~ s/\s+$//;
+
+       # transform to pre1.8 client definitions
+       @clients = split(/\n/,$filtersettings{'BANNED_CLIENTS'});
+       undef $filtersettings{'BANNED_CLIENTS'};
+       foreach(@clients)
+       {
+               s/^\s+//g; s/\s+$//g; s/\s+-\s+/-/g; s/\s+/ /g; s/\n//g;
+               $filtersettings{'BANNED_CLIENTS'} .= "$_ ";
+       }
+       $filtersettings{'BANNED_CLIENTS'} =~ s/\s+$//;
+
        &writeconfigfile;
 
        delete $filtersettings{'CUSTOM_BLACK_DOMAINS'};
@@ -2418,6 +2542,13 @@ sub savesettings
        delete $filtersettings{'BACKGROUND'};
        delete $filtersettings{'UPDATEFILE'};
 
+       &General::system("chown", "-R", "nobody.nobody", "$dbdir");
+       &General::system('/usr/bin/squidGuard', '-C', 'custom/allowed/domains');
+       &General::system('/usr/bin/squidGuard', '-C', 'custom/allowed/urls');
+       &General::system('/usr/bin/squidGuard', '-C', 'custom/blocked/domains');
+       &General::system('/usr/bin/squidGuard', '-C', 'custom/blocked/urls');
+       &setpermissions ($dbdir);
+
        &General::writehash("${General::swroot}/urlfilter/settings", \%filtersettings);
 }
 
@@ -2426,20 +2557,15 @@ sub savesettings
 sub readblockcategories
 {
        undef(@categories);
-       foreach $blacklist (<$dbdir/*>) {
-         if (-d $blacklist) {
-           $lastslashpos = rindex($blacklist,"/");
-           if ($lastslashpos > -1) {
-             $section = substr($blacklist,$lastslashpos+1);
-           } else {
-             $section = $blacklist;
-           }
-           if (!($section eq 'custom')) { push(@categories,$section) };
-         }
-       }
+
+       &getblockcategory ($dbdir);
+
+       foreach (@categories) { $_ = substr($_,length($dbdir)+1); }
 
        @filtergroups = @categories;
+
        foreach (@filtergroups) {
+               s/\//_/g;
                tr/a-z/A-Z/;
                $_ = "FILTER_".$_;
        }
@@ -2447,6 +2573,23 @@ sub readblockcategories
 
 # -------------------------------------------------------------------
 
+sub getblockcategory
+{
+       foreach $category (<$_[0]/*>)
+       {
+               if (-d $category)
+               {
+                       if ((-e "$category/domains") || (-e "$category/urls"))
+                       {
+                               unless ($category =~ /\bcustom\b/) { push(@categories,$category); }
+                       }
+                       &getblockcategory ($category);
+               }
+       }
+}
+
+# -------------------------------------------------------------------
+
 sub readcustomlists
 {
        if (-e "$dbdir/custom/blocked/domains") {
@@ -2511,7 +2654,7 @@ sub aggregatedconstraints
                        foreach (@new)
                        {
                                @tmp2 = split(/\,/);
-                               if ($tmp2[15] eq 'on')
+                               if (($tmp1[15] eq 'on') && ($tmp2[15] eq 'on'))
                                {
                                        if (($tmp1[0] eq $tmp2[0]) && ($tmp1[12] eq $tmp2[12]) && ($tmp1[13] eq $tmp2[13]) && ($tmp1[14] eq $tmp2[14]))
                                        {
@@ -2553,11 +2696,33 @@ sub aggregatedconstraints
 
 # -------------------------------------------------------------------
 
+sub setpermissions
+{
+       my $bldir = $_[0];
+
+       foreach $category (<$bldir/*>)
+       {
+                if (-d $category){
+                       &General::system("chmod", "755", "$category");
+                       foreach $blacklist (<$category/*>)
+                       {
+                               if (-f $blacklist) { &General::system("chmod", "644", "$blacklist"); }
+                               if (-d $blacklist) { &General::system("chmod", "755", "$blacklist"); }
+                       }
+                       # XXX uses globbing
+                       system("chmod 666 $category/*.db &> /dev/null");
+                       &setpermissions ($category);
+               }
+        }
+}
+
+# -------------------------------------------------------------------
+
 sub writeconfigfile
 {
-       my $executables = "\\.\(ade|adp|asx|bas|bat|chm|com|cmd|cpl|crt|dll|eml|exe|hiv|hlp|hta|inc|inf|ins|isp|jse|jtd|lnk|msc|msh|msi|msp|mst|nws|ocx|oft|ops|pcd|pif|plx|reg|scr|sct|sha|shb|shm|shs|sys|tlb|tsp|url|vbe|vbs|vxd|wsc|wsf|wsh\)\$";
-       my $audiovideo = "\\.\(aiff|asf|avi|dif|divx|mov|movie|mp3|mpe?g?|mpv2|ogg|ra?m|snd|qt|wav|wmf|wmv\)\$";
-       my $archives = "\\.\(bin|bz2|cab|cdr|dmg|gz|hqx|rar|smi|sit|sea|tar|tgz|zip\)\$";
+       my $executables = "/[^/]*\\.\(ade|adp|asx|bas|bat|chm|com|cmd|cpl|crt|dll|eml|exe|hiv|hlp|hta|inc|inf|ins|isp|jse|jtd|lnk|msc|msh|msi|msp|mst|nws|ocx|oft|ops|pcd|pif|plx|reg|scr|sct|sha|shb|shm|shs|sys|tlb|tsp|url|vbe|vbs|vxd|wsc|wsf|wsh\)\$";
+       my $audiovideo = "/[^/]*\\.\(aiff|asf|avi|dif|divx|flv|mkv|mov|movie|mp3|mp4|mpe?g?|mpv2|ogg|ra?m|snd|qt|wav|wma|wmf|wmv\)\$";
+       my $archives = "/[^/]*\\.\(7z|bin|bz2|cab|cdr|dmg|gz|hqx|rar|smi|sit|sea|tar|tgz|zip\)\$";
 
        my $ident = " anonymous";
 
@@ -2606,9 +2771,9 @@ sub writeconfigfile
                        if ($filtersettings{'SHOW_URL'} eq 'on') { $redirect .= "&url=%u"; }
                        if ($filtersettings{'SHOW_IP'} eq 'on') { $redirect .= "&ip=%a"; }
                        $redirect  =~ s/^&/?/;
-                       $redirect = "http:\/\/$netsettings{'GREEN_ADDRESS'}:81\/redirect.cgi".$redirect; 
+                       $redirect = "http:\/\/$netsettings{'GREEN_ADDRESS'}:$http_port\/redirect.cgi".$redirect;
                } else {
-                       $redirect="http:\/\/$netsettings{'GREEN_ADDRESS'}:81\/redirect.cgi";
+                       $redirect="http:\/\/$netsettings{'GREEN_ADDRESS'}:$http_port\/redirect.cgi";
                }
        } else { $redirect=$filtersettings{'REDIRECT_PAGE'}; }
 
@@ -2653,6 +2818,8 @@ sub writeconfigfile
                $defaultrule .= "any";
        }
 
+       $defaultrule =~ s/\//_/g;
+
        open(FILE, ">${General::swroot}/urlfilter/squidGuard.conf") or die "Unable to write squidGuard.conf file";
        flock(FILE, 2);
 
@@ -2669,45 +2836,35 @@ sub writeconfigfile
                }
        }
 
-       if ((($filtersettings{'ENABLE_REWRITE'} eq 'on') && (@repositoryfiles)) || ($filtersettings{'ENABLE_SAFESEARCH'} eq 'on'))
-       {
-               print FILE "rewrite rew-rule-0 {\n";
+       if (($filtersettings{'ENABLE_REWRITE'} eq 'on') && (@repositoryfiles)) {
+               print FILE "rewrite rew-rule-1 {\n";
 
-               if (($filtersettings{'ENABLE_REWRITE'} eq 'on') && (@repositoryfiles))
+               print FILE "    # rewrite localfiles\n";
+               foreach (@repositoryfiles)
                {
-                       print FILE "    # rewrite localfiles\n";
-                       foreach (@repositoryfiles)
-                       {
-                               print FILE "    s@.*/$_\$\@http://$netsettings{'GREEN_ADDRESS'}:81/repository/$_\@i\n";
-                       }
+                       print FILE "    s@.*/$_\$\@http://$netsettings{'GREEN_ADDRESS'}:$http_port/repository/$_\@i\n";
                }
-
-               if ($filtersettings{'ENABLE_SAFESEARCH'} eq 'on')
-               {
-                       print FILE "    # rewrite safesearch\n";
-                       print FILE "    s@(.*\\Wgoogle\\.\\w+/(webhp|search|imghp|images|grphp|groups|frghp|froogle)\\?)(.*)(\\bsafe=\\w+)(.*)\@\\1\\3safe=strict\\5\@i\n";
-                       print FILE "    s@(.*\\Wgoogle\\.\\w+/(webhp|search|imghp|images|grphp|groups|frghp|froogle)\\?)(.*)\@\\1safe=strict\\\&\\3\@i\n";
-                       print FILE "    s@(.*\\Wsearch\\.yahoo\\.\\w+/search\\W)(.*)(\\bvm=\\w+)(.*)\@\\1\\2vm=r\\4\@i\n";
-                       print FILE "    s@(.*\\Wsearch\\.yahoo\\.\\w+/search\\W.*)\@\\1\\\&vm=r\@i\n";
-                       print FILE "    s@(.*\\Walltheweb\\.com/customize\\?)(.*)(\\bcopt_offensive=\\w+)(.*)\@\\1\\2copt_offensive=on\\4\@i\n";
-               }
-
                print FILE "}\n\n";
+       }
 
-               if ((!($filtersettings{'UNFILTERED_CLIENTS'} eq '')) && ($filtersettings{'ENABLE_SAFESEARCH'} eq 'on')) {
-                       print FILE "rewrite rew-rule-1 {\n";
-                       if (($filtersettings{'ENABLE_REWRITE'} eq 'on') && (@repositoryfiles))
+       if (!($filtersettings{'UNFILTERED_CLIENTS'} eq '')) {
+               print FILE "src unfiltered {\n";
+               print FILE "    ip $filtersettings{'UNFILTERED_CLIENTS'}\n";
+               print FILE "}\n\n";
+       }
+       if (!($filtersettings{'BANNED_CLIENTS'} eq '')) {
+               print FILE "src banned {\n";
+               print FILE "    ip $filtersettings{'BANNED_CLIENTS'}\n";
+               if ($filtersettings{'ENABLE_LOG'} eq 'on')
+               {
+                       if ($filtersettings{'ENABLE_CATEGORY_LOG'} eq 'on')
                        {
-                               print FILE "    # rewrite localfiles\n";
-                               foreach (@repositoryfiles)
-                               {
-                                       print FILE "    s@.*/$_\$\@http://$netsettings{'GREEN_ADDRESS'}:81/repository/$_\@i\n";
-                               }
+                               print FILE "    logfile       ".$ident." banned.log\n";
                        } else {
-                               print FILE "    # rewrite nothing\n";
+                               print FILE "    logfile       ".$ident." urlfilter.log\n";
                        }
-                       print FILE "}\n\n";
                }
+               print FILE "}\n\n";
        }
 
        if (-e $uqfile)
@@ -2756,7 +2913,30 @@ sub writeconfigfile
                        {
                                $idx++;
                                print FILE "src network-$idx {\n";
-                               print FILE "    ip $tc[12]\n";
+                               @clients = split(/ /,$tc[12]);
+                               @temp = split(/-/,$clients[0]);
+                               if ( (&General::validipormask($temp[0])) || (&General::validipandmask($temp[0])))
+                               {
+                                       print FILE "    ip $tc[12]\n";
+                               } else {
+                                       print FILE "    user";
+                                       @clients = split(/ /,$tc[12]);
+                                       foreach $line (@clients)
+                                       {
+                                               $line =~ s/(^\w+)\\(\w+$)/$1%5c$2/;
+                                               print FILE " $line";
+                                       }
+                                       print FILE "\n";
+                               }
+                               if (($filtersettings{'ENABLE_LOG'} eq 'on') && ($tc[14] eq 'block') && ($tc[13] eq 'any'))
+                               {
+                                       if ($filtersettings{'ENABLE_CATEGORY_LOG'} eq 'on')
+                                       {
+                                               print FILE "    logfile       ".$ident." timeconst.log\n";
+                                       } else {
+                                               print FILE "    logfile       ".$ident." urlfilter.log\n";
+                                       }
+                               }
                                print FILE "}\n\n";
                        }
                }
@@ -2776,31 +2956,40 @@ sub writeconfigfile
                }
        }
 
-       if (!($filtersettings{'UNFILTERED_CLIENTS'} eq '')) {
-               print FILE "src unfiltered {\n";
-               print FILE "    ip $filtersettings{'UNFILTERED_CLIENTS'}\n";
-               print FILE "}\n\n";
-       }
-       if (!($filtersettings{'BANNED_CLIENTS'} eq '')) {
-               print FILE "src banned {\n";
-               print FILE "    ip $filtersettings{'BANNED_CLIENTS'}\n";
-               print FILE "}\n\n";
-       }
-
        foreach $category (@categories) {
+               $blacklist = $category;
+               $category =~ s/\//_/g;
+
+               if ( $filtersettings{"FILTER_".uc($category)} ne "on" ){
+                       my $constraintrule = "false";
+
+                       foreach (@tclist){
+                               chomp;
+                               @tc = split(/\,/);
+                               $tc[13] =~ s/\//_/g;
+                               if ($tc[15] eq 'on' && $tc[13] =~ $category){
+                                       $constraintrule = "true";
+                               }
+                       }
+
+                       if ( $constraintrule eq "false"){
+                               next;
+                       }
+               }
+
                print FILE "dest $category {\n";
-               if (-e "$dbdir/$category/domains") {
-                       print FILE "    domainlist     $category\/domains\n";
+               if (-e "$dbdir/$blacklist/domains") {
+                       print FILE "    domainlist     $blacklist\/domains\n";
                }
-               if (-e "$dbdir/$category/urls") {
-                       print FILE "    urllist        $category\/urls\n";
+               if (-e "$dbdir/$blacklist/urls") {
+                       print FILE "    urllist        $blacklist\/urls\n";
                }
-               if ((-e "$dbdir/$category/expressions") && ($filtersettings{'ENABLE_EXPR_LISTS'} eq 'on')) {
-                       print FILE "    expressionlist $category\/expressions\n";
+               if ((-e "$dbdir/$blacklist/expressions") && ($filtersettings{'ENABLE_EXPR_LISTS'} eq 'on')) {
+                       print FILE "    expressionlist $blacklist\/expressions\n";
                }
-               if (($category eq 'ads') && ($filtersettings{'ENABLE_EMPTY_ADS'} eq 'on'))
+               if ((($category eq 'ads') || ($category eq 'adv')) && ($filtersettings{'ENABLE_EMPTY_ADS'} eq 'on'))
                {
-                       print FILE "    redirect       http:\/\/$netsettings{'GREEN_ADDRESS'}:81\/images/urlfilter/1x1.gif\n";
+                       print FILE "    redirect       http:\/\/$netsettings{'GREEN_ADDRESS'}:$http_port\/images/urlfilter/1x1.gif\n";
                }
                if ($filtersettings{'ENABLE_LOG'} eq 'on')
                {
@@ -2812,8 +3001,9 @@ sub writeconfigfile
                        }
                }
                print FILE "}\n\n";
+               $category = $blacklist;
        }
-       
+
        print FILE "dest files {\n";
        print FILE "    expressionlist custom\/blocked\/files\n";
        if ($filtersettings{'ENABLE_LOG'} eq 'on')
@@ -2863,10 +3053,6 @@ sub writeconfigfile
        if (!($filtersettings{'UNFILTERED_CLIENTS'} eq '')) {
                print FILE "    unfiltered {\n";
                print FILE "        pass all\n";
-               if ($filtersettings{'ENABLE_SAFESEARCH'} eq 'on')
-               {
-                       print FILE "        rewrite rew-rule-1\n";
-               }
                print FILE "    }\n\n";
        }
        if (!($filtersettings{'BANNED_CLIENTS'} eq '')) {
@@ -2917,6 +3103,7 @@ sub writeconfigfile
                        chomp;
                        @tc = split(/\,/);
                        @ec = split(/\|/,$tc[13]);
+                       foreach (@ec) { s/\//_/g; }
                        if ($tc[15] eq 'on')
                        {
                                $idx++;
@@ -2962,12 +3149,17 @@ sub writeconfigfile
                                                print FILE $tcrule unless ((@ec == 1) && ($ec[0] eq 'any'));
                                        } else {
                                                $tcrule = $defaultrule;
-                                               foreach (@ec)
+                                               if ((@ec == 1) && ($ec[0] eq 'any'))
                                                {
-                                                       $tcrule =~ s/!$_ //;
-                                                       print FILE "$_ " if ($_ eq 'any');
+                                                       print FILE "any";
+                                               } else {
+                                                       foreach (@ec)
+                                                       {
+                                                               $tcrule = "$_ ".$tcrule unless (index($defaultrule,"!".$_." ") ge 0);
+                                                               $tcrule =~ s/!$_ //;
+                                                       }
+                                                       print FILE $tcrule;
                                                }
-                                               print FILE $tcrule unless ((@ec == 1) && ($ec[0] eq 'any'));
                                        }
                                }
 
@@ -2989,9 +3181,9 @@ sub writeconfigfile
                        print FILE "        logfile".$ident." urlfilter.log\n";
                }
        }
-       if ((($filtersettings{'ENABLE_REWRITE'} eq 'on') && (@repositoryfiles)) || ($filtersettings{'ENABLE_SAFESEARCH'} eq 'on'))
+       if (($filtersettings{'ENABLE_REWRITE'} eq 'on') && (@repositoryfiles))
        {
-               print FILE "        rewrite rew-rule-0\n";
+               print FILE "        rewrite rew-rule-1\n";
        }
        print FILE "        redirect $redirect\n";
        print FILE "    }\n";