#!/usr/bin/perl -w
# NAME: chkziptxt.pl
# AIM: Read an input file as a ZIP.TXT - a text listing of a big ZIP file
# Quite specialised, in that this file MUST contain MY MD5 output exactly
# 08/11/2011 geoff mclane http://geoffair.net/mperl
use strict;
use warnings;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use Cwd;
use Time::Local;
my $perl_dir = 'C:\GTools\perl';
unshift(@INC, $perl_dir);
require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n";
# log file stuff
our ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
    my @tmpsp = split(/(\\|\/)/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $outfile = $perl_dir."\\temp.$pgmname.txt";
open_log($outfile);

# user variables
my $VERS = "0.0.1 2011-11-03";
my $load_log = 0;
my $in_file = '';
my $verbosity = 0;
my $debug_on = 0;
my $def_file = 'def_file';
my $out_xml = '';

### program variables
my @warnings = ();
my $cwd = cwd();
my $os = $^O;
my @input_files = ();
my @excluded = ();

# DEBUG items
my $dbg_02 = 0;

sub VERB1() { return $verbosity >= 1; }
sub VERB2() { return $verbosity >= 2; }
sub VERB5() { return $verbosity >= 5; }
sub VERB9() { return $verbosity >= 9; }

sub show_warnings($) {
    my ($val) = @_;
    if (@warnings) {
        prt( "\nGot ".scalar @warnings." WARNINGS...\n" );
        foreach my $itm (@warnings) {
           prt("$itm\n");
        }
        prt("\n");
    } else {
        prt( "\nNo warnings issued.\n\n" ) if (VERB9());
    }
}

sub pgm_exit($$) {
    my ($val,$msg) = @_;
    if (length($msg)) {
        $msg .= "\n" if (!($msg =~ /\n$/));
        prt($msg);
    }
    show_warnings($val);
    close_log($outfile,$load_log);
    exit($val);
}


sub prtw($) {
   my ($tx) = shift;
   $tx =~ s/\n$//;
   prt("$tx\n");
   push(@warnings,$tx);
}

sub is_in_excluded($) {
    my $fil = shift;
    my ($tst);
    $fil = lc(path_u2d($fil));
    foreach $tst (@excluded) {
        $tst = lc($tst);
        return 1 if ($fil eq $tst);
    }
    return 0;
}

sub is_zip_ext($) {
    my ($ext) = shift;
    return 1 if (($ext =~ /^\.zip/i)||($ext =~ /^\.gz/i)||($ext =~ /^\.bz2/i)||($ext =~ /^\.tgz/i));
    return 0;
}
sub is_html_ext($) {
    my ($ext) = shift;
    return 1 if (($ext =~ /^\.htm/i)||($ext =~ /^\.html/i));
    return 0;
}
sub is_txt_ext($) {
    my ($ext) = shift;
    return 1 if ($ext =~ /^\.txt/i);
    return 0;
}

sub is_zip_file($) {
    my ($fil) = shift;
    my ($nm,$dir,$ext) = fileparse($fil , qr/\.[^.]*/ );
    return is_zip_ext($ext);
}

sub is_html_file($) {
    my ($fil) = shift;
    my ($nm,$dir,$ext) = fileparse($fil , qr/\.[^.]*/ );
    return is_html_ext($ext);
}

sub datetime_to_seconds($) {
    my ($date) = shift;
    if ($date =~ /^(\d{4}).{1}(\d{2}).{1}(\d{2})\s+(\d{2}).+(\d{2}).+(\d{2})\s*$/) {
        my $year = $1;
        my $mth = $2;
        my $day = $3;
        my $hrs = $4;
        my $min = $5;
        my $sec = $6;
        my $es = timelocal($sec,$min,$hrs,$day,$mth-1,$year); 
        prt( "datatime: $year/$mth/$day $hrs:$min:$sec = $es\n" ) if ($dbg_02);
        return $es;
    } else {
        pgm_exit(1,"ERROR: DateTime passed [$date] FAILED!\n");
    }
    return 0;
}


sub is_zip_text_file($$) {
    my ($fil,$rh) = @_;
    my ($nm,$dir,$ext) = fileparse($fil , qr/\.[^.]*/ );
    my $fnd = 0;
    if (is_txt_ext($ext)) {
        # ok first part OK - ends in .txt
        my ($nm2,$dir2,$ext2) = fileparse($nm , qr/\.[^.]*/ );
        if (is_zip_ext($ext2)) {
            # ok 2nd part OK - ends in .zip (type)
            if (open FIL,"<$fil") {
                my @lines = <FIL>;
                close FIL;
                # got file lines - seek 2 lines
                # MD5 ("fgfs-data-03.zip") = e7500f10c5753614b0f460e556807a94
                # file [fgfs-data-03.zip], of 861,897,303 bytes, dated 2008-11-30 19:23:25 (utc).
                my ($line,$file,$md5,$file2,$nn,$date,$size,$time,$esecs);
                foreach $line (@lines) {
                    chomp $line;
                    if ($line =~ /MD5\s+\((.+)\)\s+=\s+(.+)$/) {
                        $file = strip_quotes($1);
                        $md5  = $2;
                        $fnd |= 1;
                    } elsif ($line =~ /file\s+\[(.+)\],\s+of\s+(.+)\s+bytes,\s+dated\s+([0-9-]+)\s+(\d{2}:\d{2}:\d{2})\s+\(utc\)\./) {
                        $file2 = $1;
                        $nn = $2;
                        $date = $3;
                        $time = $4;
                        $size = $nn;
                        $size =~ s/,//g;
                        $esecs = datetime_to_seconds("$date $time");
                        $fnd |= 2;
                    }
                    last if ($fnd == 3);
                }
                if ($fnd == 3) {
                    if (($file eq $nm)&&($file2 eq $nm)) {
                        ${$rh}{'FILE'} = $file;
                        ${$rh}{'MD5'} = $md5;
                        ${$rh}{'BYTES'} = $nn;
                        ${$rh}{'DATE'} = $date;
                        ${$rh}{'SIZE'} = $size;
                        ${$rh}{'ESECS'} = $esecs;
                        return 1;
                    } else {
                        prtw("WARNING: MD5 names [$file] [$file2] DO NOT MATCH [$fil]\n");
                    }
                } else {
                    prtw("WARNING: Failed find MD5 lines in [$fil]\n");
                }
            } else {
                prtw("WARNING: Failed to open [$fil]\n");
            }
        }
    }
    return 0;
}


sub process_in_file($) {
    my ($inf) = @_;
    my %hash = ();
    my $rh = \%hash;
    my ($sf,$md5,$dtt,$nn,$sz,$es);
    if (is_zip_text_file($inf,$rh)) {
        $sf  = ${$rh}{'FILE'};
        $md5 = ${$rh}{'MD5'};
        $dtt = ${$rh}{'DATE'};
        $nn  = ${$rh}{'BYTES'};
        $sz  = ${$rh}{'SIZE'};
        $es  = ${$rh}{'ESECS'};
        prt("[$dtt] [$sf] [$nn] [$md5] (TEXT)\n");
    } else {
        prt("File $inf does NOT appear to be a ZIP.TXT type file!\n");
    }
}

#########################################
### MAIN ###
parse_args(@ARGV);
foreach my $file (@input_files) {
    next if (is_in_excluded($file));
    process_in_file($file);
}
pgm_exit(0,"");
########################################
sub give_help {
    prt("$pgmname: version $VERS\n");
    prt("Usage: $pgmname [options] in-file\n");
    prt("Options:\n");
    prt(" --help  (-h or -?) = This help, and exit 0.\n");
    prt(" --verb[n]     (-v) = Bump [or set] verbosity. def=$verbosity\n");
    prt(" --load        (-l) = Load LOG at end. ($outfile)\n");
    #prt(" --out <file>  (-o) = Write output to this file.\n");
}

sub need_arg {
    my ($arg,@av) = @_;
    pgm_exit(1,"ERROR: [$arg] must have a following argument!\n") if (!@av);
}

sub got_wild($) {
    my $file = shift;
    return 1 if ($file =~ /(\?|\*)/);
    return 0;
}

sub parse_args {
    my (@av) = @_;
    my ($arg,$sarg);
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /^-/) {
            $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /^-/);
            if (($sarg =~ /^h/i)||($sarg eq '?')) {
                give_help();
                pgm_exit(0,"Help exit(0)");
            } elsif ($sarg =~ /^v/) {
                if ($sarg =~ /^v.*(\d+)$/) {
                    $verbosity = $1;
                } else {
                    while ($sarg =~ /^v/) {
                        $verbosity++;
                        $sarg = substr($sarg,1);
                    }
                }
                prt("Verbosity = $verbosity\n") if (VERB1());
            } elsif ($sarg =~ /^l/) {
                $load_log = 1;
                prt("Set to load log at end.\n") if (VERB1());
            #} elsif ($sarg =~ /^o/) {
            #    need_arg(@av);
            #    shift @av;
            #    $sarg = $av[0];
            #    $out_xml = $sarg;
            #    prt("Set out file to [$out_xml].\n") if (VERB1());
            } elsif ($sarg =~ /^x/) {
                need_arg(@av);
                shift @av;
                $sarg = $av[0];
                push(@excluded,$sarg);
                if (-f $sarg) {
                    prt("Set to exclude [$sarg]\n");
                } else {
                    prt("Would exclude [$sarg], but does not appear to exist?\n");
                }
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            $in_file = $arg;
            if (got_wild($arg)) {
                my @arr = glob($arg);
                if (@arr) {
                    push(@input_files,@arr);
                    prt("Set wild to [$in_file], glob ".scalar @arr." files.\n");
                    $in_file = $arr[0];
                } else {
                    pgm_exit(1,"ERROR: glob($arg) did NOT yield an files!\n");
                }
            } else {
                push(@input_files,$in_file);
                prt("Set input to [$in_file]\n");
            }
        }
        shift @av;
    }

    if ((length($in_file) ==  0) && $debug_on) {
        $in_file = $def_file;
        push(@input_files,$in_file);
    }
    if (length($in_file) ==  0) {
        pgm_exit(1,"ERROR: No input files found in command!\n");
    }
    if (! -f $in_file) {
        pgm_exit(1,"ERROR: Unable to find in file [$in_file]! Check name, location...\n");
    }
}

# eof - template.pl
