#!/usr/bin/perl -w # # Prochosts.pl downloads a new hosts file, and searches it for entries not in the old one # it adds what it finds to the bottom of a new hosts file and distributes it to all machines # in a local network (including local machine). It also allows local overrides of bad and good sites. # Tested using ActivePerl 5.8 on WinXP. # # # the optional manualhosts.txt file consists of # # 1) A line with "OK" (no quotes) followed by more than 0 lines with # # URLs (www.xxx.yyy) which are permitted even if they are blocked by # # the hosts file # # # # 2) A line with "BLOCK" (no quotes) followed by more than 0 lines # # with URLs (www.xxx.yyy) which will be blocked even if they do not # # appear in the hosts file # # # # 3) (optional) blank lines or comments. Comments have a # in column 1 # # Note: The folder in which this script is run needs a \old subfolder or script will fail. # # By Jeff Winston http://www.kwcpa.com/tools tools@kwcpa.com # Rev. 1.0, 11/16/09 Copyright (C) 2009 # Rev. 1.1, 12/ 6/09 Copyright (C) 2009 Bug fixes # Rev. 1.2, 1/21/10 Copyright (C) 2010 Bug fixes # # --------------------------------------------------------------------- # 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 2 # 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, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, # USA. or check out http://www.gnu.org/copyleft/gpl.html # --------------------------------------------------------------------- # use LWP::simple; $|=1; $debug=0; # host file destinations # add other machines to list by using the format: # "\\\\\\\\windows\\system32\\drivers\\etc\\hosts" @locations = ("c:\\windows\\system32\\drivers\\etc\\hosts"); # figure out the date, we'll need it ($day, $month, $year) = (localtime)[3,4,5]; $month = $month + 1; $year = $year - 100; $date = sprintf "%02s_%02s_%02s",$month,$day,$year; # URL, filenames $hosts_url = "http://mvps.org/winhelp2002/hosts.txt"; $master = "masterhosts.txt"; # existing hosts file $hostfile = "hosts.txt"; # raw new hostfile $manhosts = "manualhosts.txt"; # manual additions to host file (see top of this script for format) $new_output = "HOSTS_" . $date; # logged copy of new hosts file # get the hosts file from the mvps site if ($debug == 0) { print "Getting a new hosts file..."; unless(@content = LWP::Simple::get($hosts_url)) { die "Failed to get hosts file at $hosts_url";} open (HFIL," > $hostfile") or die "Failed to open $hostfile"; foreach $line (@content) {print HFIL $line;} print "written\n"; } close (HFIL); %blocksites=(); $cnt=0; @mas_lines=(); # read in the current file, build a hash of all existing blocked websites if (-e $master) { open (MFILE, "< $master") or die "error opening $master\n"; while (defined ($line = )) { $cnt++; chomp $line; # get rid of ^M at end of line while (substr($line,-1,1) eq "\r") { $line = substr($line,0,-1); } $dup=0; if ((substr($line,0,1) ne "\#") && (length($line) > 10)) { @tokens = split " ",$line; if ($tokens[0] eq "127.0.0.1") { if ($#tokens == 0) { print "$master: Bad line $cnt $line\n"; } else { if (exists($blocksites{$tokens[1]})) { $dup=1; } else { $blocksites{$tokens[1]} = 0; } } } } # don't print lines that are duplicates if ($dup == 0) { push @mas_lines, $line; } } close (MFILE); } # read in manual specification file if one exists if (-e $manhosts) { open (OFILE, "< $manhosts") or die "error opening $manhosts\n"; $ok=0; while (defined ($line = )) { chomp $line; # get rid of ^M at end of line while (substr($line,-1,1) eq "\r") { $line = substr($line,0,-1); } if ((substr($line,0,1) ne "\#") && (length($line) > 1)) { if ($line =~ "OK") { $ok = 1; } elsif ($line =~ "BLOCK") { $ok = 0; } else { @tokens = split " ",$line; if ($ok == 1) { push @goodsites, $tokens[0]; } else { #only add bad sites not in original file if (!(exists($blocksites{$tokens[0]}))) { push @badsites, $tokens[0]; $blocksites{$tokens[0]} = 1; } } } } } close (OFILE); } $cnt=0; # read in the new file, build a list of all websites not in the current list open (HFIL, "< $hostfile") or die "Failed to open $hostfile"; while(defined($line=)) { $cnt++; if ((substr($line,0,1) ne "\#") && (length($line) > 10)) { chomp $line; # get rid of ^M at end of line while (substr($line,-1,1) eq "\r") { $line = substr($line,0,-1); } @tokens = split " ",$line; if ($tokens[0] eq "127.0.0.1") { if ($#tokens == 0) { print "$hostfile: Bad line $cnt $line\n"; } else { # only add bad sites not in original file if (!(exists($blocksites{$tokens[1]}))) { $blocksites{$tokens[1]} = 1; push @newlines, "$line\n"; } } } } } close (HFIL); # skim both master and new lists and remove matches to good list foreach $line (@mas_lines) { $ok=1; foreach $site (@goodsites) { if ($line =~ $site) { $ok=0; last; } } if ($ok == 1) { push @mas_lines2, $line; } } foreach $line (@newlines) { $ok=1; foreach $site (@goodsites) { if ($line =~ $site) { $ok=0; last; } } if ($ok == 1) { push @newlines2, $line; } } # open the output file open (OUTFIL, "> $new_output") or die "error opening $new_output\n"; # init print OUTFIL "# Generated by PROCHOSTS.PL on $date\n"; # print the sites from the original file foreach $line (@mas_lines2) { print OUTFIL "$line\n"; } # and the new sites if ($#newlines2 > -1) { print OUTFIL "\n# Sites added $date\n"; foreach $line (@newlines2) { print OUTFIL $line; } } # and the extra sites $head=0; foreach $line (@badsites) { if ($head == 0) { print OUTFIL "\n# Sites explicitly added $date\n"; $head=1; } print OUTFIL "127.0.0.1 $line\n"; print "127.0.0.1 $line\n"; } #we're done close (OUTFIL); if ($debug == 1) {exit;} # update files if (-e $master) { `del $master`; } if (!(-e "old")) { print "Attempting to create subdir \"old\"...\n"; system("mkdir old"); } `copy $new_output old\\$new_output`; `move $new_output $master`; # distribute host files foreach $loc (@locations) { print "updating $loc\n"; `attrib -r -s -h $loc`; `copy $master $loc`; `attrib +r +s +h $loc`; } system("pause");