#!/usr/local/bin/perl # # ZipComment # V1.3 pl 02 - 30 May 1998 # # Written by # Jouko Valta (jopi@x2ftp.oulu.fi) # # # List ZIP files with a zip-comment in current directory hierarchy # to remove ZIP comments or to trace ones that have slipped the test. # Also looks for that lame demo from ACE... # # Options # -b backup # -f display filenames # -g debug mesages # -log Specify the Log File. Defaults none. # -q Silent mode. Don't print 'Scanning' messages. # -v Verbose mode. # -t Test only. # -i Interactively remove files and ZIP comments found. # -z Automatically remove ZIP comments found. # -nd Don't remove files. # -nz Don't remove ZIP comments. # # Return Values # 0 Completed succesfully # 1 Error occurred # 2 Processing interrupted # # # V1.0 - 25 Jun 1996 # Recognizes ACE, BBS, as well as TLF-TDV programming group ads. # By option, backups any affected files on /var/tmp. (Default true.) # # V1.1 - 26 Jun 1996 # Desired files can be specified on the command line. # ACE *.com files limited beetween 2100 and 4000 bytes. # Several bug fixes and some code reorganisation. # Writes list of actions perfomed onto Log File. # # V1.1 pl 01 - 9 Jul 1996 # Missing CR's added to print $_; # # V1.1 pl 02 - 23 Aug 1996 # GEES_BBS.EXE trapped now... # Don't ask for stripping ACE comment after deleting the files. # # V1.1 pl 03 - 11 Jan 1997 # Backups moved to /pc/log/backup; upon failure reverts to /var/tmp. # # V1.2 pl 00 - 18 Mar 1997 # Strict "Call" rules # Beep when attention needed. # # V1.2 pl 01 - 9 Apr 1997 # Added GuruHeaven / PaskaSoft Productions # Added PWA, BB^II, RISC and GM/MiRAGE BBS'es. # Added Temple BBS # Trap any .NFO files discarding case. # "This file passed ..." trapped now. # TWT and GARBAGE seem to be programming groups. Nothing done yet. # # V1.3 pl 00 - 17 Apr 1997 # -t test-only option # Added Toronto VRSIG BBS, OF BBS, PA BBS, TFL-TDV.APP, SHOCK! Group # Added GUIBBS (.com file) and PARANOIDS. # Notify about *.APP and *.BBS files. # Handling comments and files isolated better. # Program layout cleared. # User may view (via pager) text files asked to delete. # Count how many files removed. # User interface enhanced. # Selective ZIP comment stripping depending on comment type. # Skip all copies of given file. # # V1.3 pl 01 - 9 Aug 1997 # Bugfix: Did not recognize ACE ads after PL 00. # Trap more 'distro sites'. # # V1.3 pl 02 - 30 May 1998 # Abyss BBS/ System Express BBS and Music BBS. # . # # @mons = ( "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" ); ($sec,$min,$hour,$mday,$Mon,$Year,$wday,$yday,$isdst) = localtime; $USAGE = "\nzipcomment [ -option ... ] [ file ... ]\ -b Make backups when deleting files from ZIP's.\ -f Print all filenames.\ -g Display debug messages.\ -log Set logging mode using file specified.\ -q Set silent mode.\ -i Ask and remove found comments and files.\ -sa Strip all comments.\ -sb Strip BBS'es comments.\ -sg Strip groups comments.\ -sp Strip pirates comments.\ -a|-nfo Check all .APP and .NFO files.\ -t test only\ -v verbose mode.\ #-d remove files.\ #-z remove ZIP comments.\ -nb don't make backups.\ -nd don't remove files.\ -nz Keep any ZIP comments.\n\n"; $UNZIP = "/usr/local/bin/unzip -l"; $ZIP = "/usr/local/bin/zip"; $FIND = "/bin/find \. -name '*.zip' -print; # | /bin/cut -c3-"; $PAGER = "| less"; # Determine Backup Directory $BACKUPDIR = "/pc/log/backup"; if (! -d $BACKUPDIR || ! -w $BACKUPDIR) { printf STDERR "Cannot access $BACKUPDIR. Please, check the setting or run\n create_dosadm_logs script.\n"; $BACKUPDIR = "/var/tmp"; } # ----------------------------------------------------------------------------- # ## ZIP Comment types # $ZC_NONE = 0; # No comment present. $ZC_ANY = 1; # Un-identified comment type $ZC_AUTHOR = 2; # Important information # Group Types # $ZC_GROUP = 4; # Lowest Group value. $ZC_PIRATE = 16; # Lowest Pirate/BBS type. Same as ZC_BBS. # Groups # $ZC_TFL_TDV = 4; # TFL-TDV Group. Several additional files enclosed. $ZC_TWT = 5; # $ZC_GARBAGE = 6; $ZC_DISTORTION = 7; # dst! (Note: Contains their legal stuff.) $ZC_SHOCK = 8; # Shock! junk... $ZC_PARANOIDS = 9; # Paranoids Demo Group (Lahti). # BBS'es (most come with additional files.) # $ZC_BBS = 16; # General BBS ad, like a BBS list. $ZC_ACE = 17; # Worst type. Needs to scan for 2 additional files. $ZC_GEES_BBS = 18; # GEES BBS: Has additional .EXE file. $ZC_GUIBBS = 19; # GUIBBS: Has .COM file. $ZC_ABYSS_BBS = 20; # Abyss BBS: systemx.nfo pcboard.nfo pcexpre.nfo, # abyss2.exe, sysxf15.exe $ZC_MUSIC_BBS = 21; # MUSiC PORT BBS: Alters the file_id.diz (!); # Files fast!art.com == freecall.com, b?tch.com # rape_me.now and music#.nfo # .nfo, .app files # $ZC_PASKA = 24; # PaskaSoft Productions. $ZC_PWA = 25; # Pirates With Attitudes BBS. $ZC_BB2 = 26; # BB2. $ZC_RISC = 27; # RISC BBS. $ZC_GM = 28; # GM/MiRAGE BBS. $ZC_TEMPLE = 29; # The Temple BBS. $ZC_OF = 30; # The O.F. BBS. $ZC_PA = 31; # The P.A. BBS. $ZC_TORONTO = 32; # Toronto Virtual Reality Special Interest Group BBS. # ----------------------------------------------------------------------------- # ## Action Modes # $NO = 0; $VERFY = 1; $AUTO = 2; # ----------------------------------------------------------------------------- # ## Defaults # $Test = 0; $Debug = 0; $Strip = $VERFY; $Delete = $VERFY; $SeekType = $ZC_GROUP; $SeekNFO = $ZC_BBS; # Check all .NFO files. Defaults NO. $Backup = 1; $Verbose = 1; $FileNames = 0; ## Command line options opt: while ($_ = $ARGV[0], /^-/) { shift; if (/^-b/) { $Backup = 1; next opt; } # make backups if (/^-f/) { $FileNames++; next opt; } # print filenames if (/^-g/) { $Debug++; next opt; } # debug messages if (/^-log/) { $LogFile = $ARGV[0]; shift; next opt; } if (/^-q/) { $FileNames = 0; $Verbose = 0; next opt; } # silent mode if (/^-i/) { $Strip = $VERFY; $Delete = $VERFY; next opt; } # Ask and remove found comments and files if (/^-sa/) { $SeekType = $ZC_ANY; next opt; } # Strip all comments if (/^-sb/) { $SeekType = $ZC_BBS; next opt; } # Strip BBS'es if (/^-sg/) { $SeekType = $ZC_GROUP; next opt; } # Strip groups if (/^-sp/) { $SeekType = $ZC_PIRATE; next opt; } # Strip pirates if (/^-a|^-nfo/){ $SeekNFO = $ZC_NONE; next opt; } # Check all .NFO's if (/^-t/) { $Test++; next opt; } # test only if (/^-v/) { $Verbose++; next opt; } # verbose mode # if (/^-d/) { $Delete = 2; next opt; } # remove files # if (/^-z/) { $Strip = 2; next opt; } # remove ZIP comments if (/^-nb/) { $Backup = 0; next opt; } # don't make backups if (/^-nd/) { $Delete = 0; next opt; } # don't remove files if (/^-nz/) { $Strip = 0; next opt; } # keep ZIP comments if (/^-/) { die $USAGE; } } # Do not truncate log file, so that zipcomment can be run as many times # as it takes. The calling program will clear the file for us. if ($LogFile) { open (L, ">> $LogFile") || die "Can't open log file '$LogFile'\n"; } ## Scan ZIP Filenames if ($ARGV[0]) { open (foo, "/bin/ls -1 @ARGV |") || die "Can't list input files"; } else { open (foo, "$FIND |") || die "Can't open $FIND"; } $ZipCount = 0; line: while () { if (/^\s*$/) { next line; } # Empty line if (/README.UPL|^00|\/00/) { next; } # Don't touch the instructions if (/junk|txt\/|reupload/) { next; } # Ignore rejected files if (/(\S+.zip)/i) { # Any Zip File $ZipFile = $1; # ZIP file open (M, "$UNZIP $ZipFile |") || print STDERR "Cannot open $ZipFile\n"; # $Verbose && printf ("Scanning file '$ZipFile'\n"); ++$ZipCount; $ads = 0; # Type of the last ad $comment= 0; # If comment present $files = 0; # Scan Mode flag: comment/file $filecnt= 0; # archived file count $saved = 0; $ZipBanner= ""; # Contents of the comment $msglen = 0; # Length of the comment $seemsg = 1; $rmcount= 0; $rmlist = ""; $comname= ""; $ans = ""; $rmverify = ""; while () { if (! $files) { $ZipBanner .= $_; # Store Zip Comment. } chop; ### General rules if (/^\s*$/) { next; } # Empty line if (/^\s*Archive:/) { # Display comment ++$seemsg; next; } if (/\[\s*(\S+)\]\s+comment:/) { # Display comment if (! $ads) { $ads = $ZC_ANY; } ++$seemsg; ++$comment; next; } ### Zip Comment parsing if (/this file passed/i || /upload/i || /downloaded from/i || /Distribution Site/i || /HeadQuarTers/i) { if (! $ads) { $ads = $ZC_BBS; # Any BBS ++$comment; } } if (/BBS|Call[\s:\.\:]|\s+call\s+|\s+lines*\s+|24h/i || /\s+againgst\s+.*virus/i) { if ($ads != $ZC_ACE) { $ads = $ZC_BBS; } if (! $files) { # Which scan mode ? printf "$ZipFile: BBS call: $_\n"; $seemsg = 0; ++$comment; } else { printf "$ZipFile: BBS file: $_\n"; } } # BBS # Identify ZIP comments. # # Find keywords in the banner. # if (/-\S-ace-|SOAP WHQ 555:330/ || /ú Ä ÄÄÄ ÄÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄ Ä ú/) { $Verbose && print "$ZipFile: ACE banner found. (Remove additional files.)\n"; $ads = $ZC_ACE; $seemsg = 0; ++$comment; # -?-ACE-? files hadled later below. } # PaskaSoft elsif (/\s+GuruHeaven\s+/i || /PaskaSoft Productions/i) { $Verbose && print "$ZipFile: GuruHeaven/Paska file.)\n"; $ads = $ZC_PASKA; ++$comment; } # Abyss BBS elsif (/\s+tested on Abyss BBS/i) { $Verbose && print "$ZipFile: Abyss file. (Remove additional files.)\n"; $ads = $ZC_ABYSS_BBS; ++$comment; } # MusicPort BBS elsif (/DOWNLOADED FROM THE MUSiC PORT BBS/i) { $Verbose && print "$ZipFile: MusicPort file. (Remove additional files.)\n"; $ads = $ZC_MUSIC_BBS; ++$comment; } # The first File entry... elsif (/^\s*Length\s+Date\s+Time\s+Name/) { # End of comment # if ($ads == $ZC_ANY) { # Possible Author comment # } $msglen = $.; # Line count $seemsg = 0; $files = 1; # Set Scan Mode } # Print line if ($seemsg) { printf "$_\n"; ++$comment; next; } if ($files) { ($FileNames) && printf "$_\n"; ++$filecnt; } # ## Zip Files parsing # # Mark known advertisement files. # Try to specify which BBS the ads. (COM, EXE or *.NFO files) # belong, so that all ads will be removed from the archive. # if (/\s+\^*(gees\Sbbs\.com)/i || /\s+\^*(gees\Sbbs\.exe)/i) { # printf "\n*** GEES_BBS ad $_ ==> $1\n"; $ads = $ZC_GEES_BBS; mark_file($1, $_); } elsif (/\s+\^*(gui\S*bbs\.com)/i || /\s+\^*(gui\S*bbs\.exe)/i) { # printf "\n*** GUIBBS ad $_ ==> $1\n"; $ads = $ZC_GUIBBS; mark_file($1, $_); } # Abyss / SystemX BBS elsif (/\s+\^*(abyss\S*\.exe)/i || /\s+\^*(sysxf\S+.exe)/i || /\s+\^*(systemx.nfo)/i || /\s+\^*(pcboard.nfo)/i || /\s+\^*(pcexpre.nfo)/i) { # printf "\n*** Abyss_BBS ad $_ ==> $1\n"; $ads = $ZC_ABYSS_BBS; mark_file($1, $_); } # MusicPort / Rape BBS (verified to be the same) elsif (/\s+\^*(fast\S*art\.com)/i || /\s+\^*(freecall\.com)/i || /\s+\^*(b\Stch\.com)/i || /\s+\^*(rape_me\.now)/i || /\s+\^*(music\S*\.nfo)/i) { # printf "\n*** MUSiC_PORT_BBS ad $_ ==> $1\n"; $ads = $ZC_MUSIC_BBS; mark_file($1, $_); } # # ACE # elsif (/\s+\^*(\-\S\-ace\S*\-\.\S\S+)/i) { # -x-ACE-x-.xx printf "\n$ZipFile: ACE BBS file: $1\n"; $ads = $ZC_ACE; mark_file($1, $_); } elsif (/^\s+(\S+).+\s+\^*(\S+\.com)$/i) { # keep last COM if ($ads == $ZC_ACE) { # Scan file list for ACE bbs ad files if (($1 > 2100 && $1 < 4000) || /^\s+(\S+).+\s+\^*(\-\S+\-\.\S\S+)/) { print "\n*** ACE ad $_ ==> $2\n"; mark_file($2, $_); } } # ACE else { # No size limits here $Debug && print "DEBUG: last com file currently '$2'\n"; $comname = $2; $comline = $_; } } # .com # Group *.NFO and *.APP files # Possibly other-products ads and membership applications # The trailing \S* prevents long filenames breaking the logic here. elsif (/\s+(\S+\.nfo\S*)/i || /\s+(\S+\.app\S*)/i || /\s+(\S+\.bbs\S*)/i) { # Unwanted Programming Group *.nfo files. if (/\s+\^*(tfl[\-\_]tdv\.nfo)/i || /\s+\^*(tfl[\-\_]tdv\.app)/i) { print "\n$ZipFile: TFL-TDV Group file: $1\n"; $ads = $ZC_TFL_TDV; mark_file($1, $_); } elsif (/\s+\^*(sc*hock\!*\.nfo)/i) { print "\n$ZipFile: SHOCK! Group file: $1\n"; $ads = $ZC_SHOCK; mark_file($1, $_); } # Try to specify which BBS. *.nfo files. # NOTE: Bevare of VENDOR.BBS -- it may be their readme file ... # General BBS ad. elsif (/\s+\^*(distsite\.nfo)/i || /\s+\^*(distsite\.bbs)/i || /\s+\^*(\S+\.bbs)/i) { print "\n$ZipFile: General BBS list file: $1\n"; if (! $ads) { $ads = $ZC_BBS; } mark_file($1, $_); } elsif (/\s+\^*(GuruHeaven\.nfo)/i) { # PaskaSoft print "\n$ZipFile: PASKA BBS file: $1\n"; $ads = $ZC_PASKA; mark_file($1, $_); } elsif (/\s+\^*(BB^II\.nfo)/i) { print "\n$ZipFile: BB2 BBS file: $1\n"; $ads = $ZC_BB2; mark_file($1, $_); } elsif (/\s+\^*(pwa\.nfo)/i) { # Pirates With Attitude print "\n$ZipFile: PWA BBS file: $1\n"; $ads = $ZC_PWA; mark_file($1, $_); } elsif (/\s+\^*(risc\.nfo)/i) { print "\n$ZipFile: RISC BBS file: $1\n"; $ads = $ZC_RISC; mark_file($1, $_); } elsif (/\s+\^*(gm\.nfo)/i) { print "\n$ZipFile: GM/MiRAGE BBS file: $1\n"; $ads = $ZC_GM; mark_file($1, $_); } elsif (/\s+\^*(temple\.nfo)/i) { print "\n$ZipFile: Temple BBS file: $1\n"; $ads = $ZC_TEMPLE; mark_file($1, $_); } # Always check these files by hand. # Whether these files will be checked or not, can be changed # via the $SeekNFO variable. else { printf "%-16s:\t$_\n", $ZipFile; # Print filename found if ($ads >= $SeekNFO) { # The only appearance. mark_file($1, $_); } } next; } # *.nfo *.app # *.BBS or BBS.* # NOTE: bbs.des (description) on docs/online21.zip is OK. if (/\s+\^*(bbs\.txt)/i) { # General BBS ad. print "\n$ZipFile: BBS file: $1\n"; $ads = $ZC_BBS; mark_file($1, $_); } elsif (/\s+\^*(.*of\.bbs)/i) { # \222of.bbs print "\n$ZipFile: O.F. BBS file: $1\n"; $ads = $ZC_OF; mark_file($1, $_); } elsif (/\s+\^*(pa\.bbs)/i) { print "\n$ZipFile: P.A. BBS file: $1\n"; $ads = $ZC_PA; mark_file($1, $_); } elsif (/\s+\^*(torvrsig\.bbs)/i) { # Toronto VR BBS. print "\n$ZipFile: Toronto VR BBS file: $1\n"; $ads = $ZC_TORONTO; mark_file($1, $_); } # print "$_\n"; } # while ZIP listing # Some error checking if (! $files || ! $filecnt) { printf "*** FATAL ERROR: Parser confused.\n"; } # Do final knock-out if ($ads == $ZC_ACE) { # Scan file list for ACE bbs ad files if ($comname && $comname ne $2 && !grep /$comname/, $rmlist) { mark_file($comname, $comline); $comname = ""; $comline = ""; } } # ACE # ----------------------------------------------------------------------------- # # Display File Information # if ($rmlist || $ads) { ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat("$ZipFile"); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =localtime($mtime); # $datestring=$mday.'-'.$mons[$mon].'-'.$year.' '.$hour.':'.$min; if($size < 1024) { $size_string="bytes"; } elsif($size/1024 < 1024) { $size=$size/1024; $size_string="kB "; } else { $size=$size/(1024*1024); $size_string="MB "; } printf ("*** %d\t%02d-%s-%d %02d:%02d %5.1f %s\t%s\n\n", $uid, $mday, $mons[$mon], $year, $hour, $min, $size, $size_string, $ZipFile); } # ----------------------------------------------------------------------------- # # Delete files on the ZIP # if ($rmlist) { printf "\nArchive: $ZipFile\nFiles: $rmlist\n"; if ($Delete == $VERFY) { do { print "\nReally delete these files? (y/n) "; chop($rmverify = ); } while (! ($rmverify =~ /^\s*y|^\s*n/i)); } if ($Delete == $AUTO || ($Delete == $VERFY && $rmverify eq 'y')) { # Backup if ($Backup) { system ("cp $ZipFile $BACKUPDIR"); ++$saved; } printf "Deleting $rmcount files on archive '$ZipFile'.\n"; $rmlist =~ s/\s\-/ \\\?/; # $rmlist =~ tr/a-z/A-Z/; system ("$ZIP -d $ZipFile $rmlist"); printf "\n"; } else { print "\nFiles kept.\n"; } } # rmlist # # Analyze comments # if ($comment) { # Any type of comment found printf "\n"; $ans = ""; # Ask and remove ZIP Comment # Stripping ACE ad is not asked, if files were removed # # Comments belov the lowest type looked for, will only be # printed, but not stripped. if ($ads >= $SeekType && $Strip == $VERFY && $ads != $ZC_ACE) { do { printf "[%s]\n", $ZipFile; printf "%cStrip message [ %d lines] (y/n/v)%c ", 7, $msglen, 7; chop($ans = ); if ($ans eq 'v') { print $ZipBanner; } } while (! ($ans =~ /^\s*[yn]/i)); } if (($Strip == $AUTO && $ads > $ZC_AUTHOR) || ($Strip == $VERFY && $ans eq 'y') || ($ads == $ZC_ACE && $rmverify eq 'y')) { # Backup if (!$saved && $Backup) { # del didn't bacup it system ("cp $ZipFile $BACKUPDIR"); } printf "Stripping comment on archive ($msglen lines).\n"; if ($LogFile) { printf L "STRIP\t%s\t%s (%d lines)\n", $ZipFile, $ads, $msglen; } if ($Verbose) { system "$ZIP -z $ZipFile < /dev/null"; } else { system "$ZIP -z $ZipFile < /dev/null > /dev/null"; } # stderr not moved print "Stripped message.\n"; } else { print "Message kept.\n"; } printf "\n\n"; } # any comment close M; } # if ZIP file } (!$ZipCount) && printf "No files to test.\n"; print "\nDone.\n"; # ----------------------------------------------------------------------------- # NOTE: This subroutine may ask the calling while loop to exit, in order to # skip any archive. sub mark_file { local ($name, $line) = @_; # printf "%16s:\t%s\n", $ZipFile, $line; ($SkipFile{$name}) && return; ($Test) && return; if ($Delete == $VERFY) { $done = 0; while (!$done++) { printf "\n[$ZipFile] $name\n"; do { printf "Select: ( Keep / Delete / View / keep All / Next .zip / Quit) "; chop($ans = ); } while (! ($ans =~ /^\s*[kdvanq]/i)); if ($ans eq 'k') { # Do nothing } elsif ($ans eq 'd') { # $tmp = $1; $tmp =~ s/^\-/\\\?/; $rmlist .= " " . $name; ++$rmcount; } elsif ($ans eq 'v') { printf "View archive: $ZipFile\tFile: $name\n\n"; system ("$UNZIP -C -p $ZipFile $name $PAGER"); $done = 0; } elsif ($ans eq 'a') { # Skip file on all archives. print STDERR "Keeping all occurrences of this file.\n"; ++$SkipFile{$name}; } elsif ($ans eq 'n') { # Skip archive print STDERR "Skipping archive.\n"; $ads = 0; $rmlist = ""; last; # Exits the main while loop } elsif ($ans eq 'q') { print STDERR "Interrupted by user.\n"; exit 2; # Interrupt by user } else { $done = 0; # Invalid input. } } # while } # elsif ($Delete == $AUTO) { # saattaa tuhota kaikki .COM ## $tmp =$1; $tmp =~ s/^\-/\\\?/; # $rmlist .= " " . $name; # ++$rmcount; # } printf "\n\n"; # Write Log if ($LogFile) { printf L "DELE\t%s\t%s\n", $ZipFile, $line; # Write line per file. } }