#!/usr/local/bin/perl -w
use strict;

#===============================================================================
# Author: Frank A. Brunotts (bruno005)
#
# This program should only be run by root.
#
# This is the "released" program. This program detects changes in release 
# directories and sends e-mail message notifications detailing which files 
# have changed since the last run and the date and time that each of the new 
# or updated files were last modified.
#===============================================================================

#===============================================================================
# FOR TESTING ONLY:
#require '/home/bruno005/develop/released/lib/vars.pl';
# FOR PRODUCTION:
require '/root/crons/released/lib/vars.pl';
#===============================================================================

use vars qw(@cfg $log @snapshot @released $bcc $from $replyto $docRoot $progranDir $find $dir $host $to $cc $timestamp $oldSnapshotArchive @oldSnapshot);
use Date::Manip;
use File::stat;
use Mail::Mailer;

# main

&startLog;				# First, start logging.
foreach (@cfg) {			# For each release directory,
  &parseConfig;				# parse the configuration settings.
  &getOldSnapshot;			# Then, get a copy of the prior snapshot.
  &takeNewSnapshot;			# Take a new snapshot.
  &compareSnapshots;			# Compare the old and new snapshots.
  &sendEmail if ($#released > -1);	# Send a message if there are new or updated files.
  &updateOldSnapshotArchive;		# Save the new snapshot as the old snapshot.
}					# Repeat until all directories have been processed.
&endLog;				# Finally, stop logging.

# subs

#===============================================================================
# Subroutine startLog
# The startLog subroutine opens the $log log file for appending and logs the 
# fact that the program was started and records the current date and time.
sub startLog {
open (LOG, ">>$log");
$timestamp = &UnixDate('today',"%d/%b/%Y:%H:%M:%S");
print LOG "$timestamp start\n";
}
#===============================================================================

#===============================================================================
# Subroutine parseConfig
# The parseConfig subroutine parses each $entry entry in the @cfg configuration 
# array. Values for $dir subdirectory, $to primary addressee, and $cc courtesy
# copy addressee are derived here.
sub parseConfig {
my $entry = $_;
chomp ($entry);
my @settings = split(/:/, $entry);
$dir = $settings[0];
$to = $settings[1];
$cc = $settings[2];
}
#===============================================================================

#===============================================================================
# Subroutine getOldSnapshot
# The getOldSnapshot subroutine retrieves a copy of the old snapshot, stored in 
# the $oldSnapshotArchive archive file.
sub getOldSnapshot {
$oldSnapshotArchive = "$progranDir/db/$dir.db";
open OLDARCHIVE, "< $oldSnapshotArchive";
@oldSnapshot = ();
@oldSnapshot = <OLDARCHIVE>;
close OLDARCHIVE;
}
#===============================================================================

#===============================================================================
# Subroutine takeNewSnapshot
# The takeNewSnapshot subroutine takes a new @snapshot snapshot. It first $find 
# finds all of the @releaseFiles files in the $dataDir release directory. Then 
# it determines the $filedate modification time for each file. Finally, the 
# @snapshot array is populated with pipe-delimited entries consisting of the 
# file name and the corresponding $filedate modification time.
sub takeNewSnapshot {
my $dataDir = "$docRoot/$dir/";
my @releaseFiles = `$find $dataDir -type f`;
@snapshot = ();
foreach (@releaseFiles) {
  chomp($_);
  my $st = stat($_);
  my $secs = $st->mtime;
  my $date = &ParseDateString("epoch $secs");
  my $filedate = &UnixDate("$date","%Y-%m-%d %T");
  my $entry = "$_|$filedate\n";
  push (@snapshot, $entry);
}
}
#===============================================================================

#===============================================================================
# Subroutine compareSnapshots
# The compareSnapshots subroutine compares the @snapshot new snapshot and the 
# @oldsnapshot old snapshot. Each $entry entry in the @snapshot new snapshot is 
# iterated through, comparing it with each $oldEntry entry in the @oldSnapshot 
# old snapshot. If a $match natch is not found, then the $entry entry is added 
# to the @released released list.
sub compareSnapshots {
@released = ();
foreach (@snapshot) {
  my $entry = $_;
  my $match = 0;
  foreach (@oldSnapshot) {
    my $oldEntry = $_;
    $match = 1 if ($entry eq $oldEntry);
  }
  push (@released, $entry) if ($match == 0);
}
}
#===============================================================================

#===============================================================================
# Subroutine sendEmail
# The sendEmail subroutine sends an e-mail notification message if there are 
# any @released new or updated release files. The $subject subject line 
# contains both the $dir release subdirectory and the $host host name. The 
# e-mail message is addressed to the $to primary addressee, with a courtesy 
# copy to the $cc courtesy copy addressee, and a blind courtesy copy to the 
# $bcc blind courtesy copy addressee. The message is made to appear to be from 
# the $from designated originating e-mail address, and the $replyto Reply-To 
# e-mail address is set. The message body contains the $host host name, the 
# $dir release subdirectory, and a listing of the $entry released files and 
# associated time stamps. The listing of the $entry released files and 
# associated time stamps is also logged.
sub sendEmail {
my $mailer = new Mail::Mailer 'sendmail';
my $subject  = "data released to /$dir directory on $host";
$mailer->open({
  To      =>      $to,
  Cc      =>      $cc,
  Bcc     =>      $bcc,
  From    =>      $from,
  ReplyTo =>      $replyto,
  Subject =>      $subject
    });
print $mailer "Data have been released to the $host server.\n\n";
print $mailer "Directory:      /$dir\n";
print $mailer "Production url: http://$host/$dir/\n";
print $mailer "\nFile & Public Release Time Stamp:\n";
foreach (@released) {
  my $entry = $_;
  $entry =~ s/\|/\t/;
  print $mailer $entry;
  print LOG "$entry";
}
$mailer->close;
}
#===============================================================================

#===============================================================================
# Subroutine updateOldSnapshotArchive
# The updateOldSnapshotArchive subroutine saves the current @snapshot snapshot 
# to the $oldSnapshotArchive archive file.
sub updateOldSnapshotArchive {
open (ARCHIVE, ">$oldSnapshotArchive");
foreach (@snapshot) {
  print ARCHIVE $_;
}
close ARCHIVE;
}
#===============================================================================

#===============================================================================
# Subroutine endLog
# The endLog subroutine logs the fact that the program has completed its 
# run and records the current date and time before closing the $log log file.
sub endLog {
$timestamp = &UnixDate('today',"%d/%b/%Y:%H:%M:%S");
print LOG "$timestamp stop\n\n";
close (LOG);
}
#===============================================================================
