[XenoCafe Logo] Click for Homepage
Home Tutorials Forum Blog Advertising Links Contact About



Automating Norton AntiVirus Definition Downloads by PHP Script

Written by Tony Bhimani
June 23, 2006

Requirements
*nix based Operating System
PHP 3, 4, 5
PHPMailer

Download the source code: fetchavdefs.tar.gz

I wrote this script for my work over a year ago. Its purpose is to download the latest Symantec Norton AntiVirus definition file from their website and store it on our shared Windows drive accessed through Samba. Once the file is downloaded an email is sent out to all employees with the link to the file instructing them to install it. Clicking the link will launch the executable and update Norton with the latest virus definition. This process may sound familiar and Symantec already has something like this called Live Update (minus the email notifications and shared drive part). So why don't we use that instead of the script? The problem is we have a terribly slow connection and downloading an 11+ meg file sucks up all the bandwidth. My work is still stuck in the dark ages and isn't necessarily willing to upgrade our internet connection. You know how companies are, it's all about the bottom line. Even though everyone complains about how slow it is nothing is being done about it. Being the proactive person I am, I wrote this script to fetch the latest virus definition. It runs via crontab in the morning before anyone gets to work. Although this script was written to fetch virus definitions you can easily modify it for your own needs.

Installation

Extract the archive to a directory like /root/scripts/avupdates or somewhere else of your choice. You'll need to edit fetchavdefs.php and change some variables that are at the top of the PHP script. They're listed below.

$defFileDest => destination directory where the file will be moved to after it's downloaded
$smtpHost => SMTP mail host that notification emails will be relayed through
$fromEmail => from address for notification emails (typically admin@yourdomain.com)

You'll also need to download a copy of PHPMailer if you'll be using the email notifications. Be sure to change the path of the require statement on line 124 of the script. There are also a couple of text files called lastdef.txt and recipients.txt. The lastdef.txt file holds the name of the last successfully downloaded virus definition file. It's used to track if the file has already been downloaded and skips it if it has been. The recipients.txt file maintains the list of email addresses to send notifications to (employee email addresses). You'll need to edit this file and enter each email address on a line of its own. If you don't plan on sending notifications then comment out the line of code on line 117. The last step is to chmod 755 the PHP script so it's executable.

Setting up the Cron job

Assuming you installed the script and related files to /root/scripts/avupdates then you can add a cron job for fetchavdefs.php to /etc/crontab like so.

00 6 * * * root /root/scripts/avupdates/fetchavdefs.php > /dev/null 2>&1

The script will run each morning at 6am and won't send any PHP error output as emails to root (if you want to receive the emails then remove the > /dev/null 2>&1).

Summary

Automating a file download can easily be accomplished through a PHP script like this. Scripts are great for automating trivial tasks like file downloads, sending email notifications, optimizing databases, exporting data, performing backups, and many other things. You don't necessarily have to use PHP to create these scripts. Perl is a powerful language that can also be used. I like to mix things up and depending on the task I may use one language over the other. In this case I chose PHP since I'm much more familiar with it. The automated antivirus file download script highlights using regular expressions to extract URL's from HTML code, tracking a past file download and ignoring any duplicate downloads, removing the old definition files to conserve disk space, and using the PHPMailer package to send out emails in HTML format.

Source Code:

#!/usr/bin/php -q
<?php 
$defFileTemp = "/tmp";
$defFileDest = "/path/Virus Defs";		// edit this: change to path of file storage
$smtpHost    = "smtp.yourdomain.com";	// edit this: change your your smtp mail server
$fromEmail   = "noreply@youdomain.com";	// edit this: change to from email address

//ini_set("memory_limit", "16M");

// HREF URL Extractor RegExp from http://www.onaje.com/php/article.php4/46

// regular expression <\s*a\s+[^>]*href\s*=\s*[\"']?([^\"' >]+)[\"' >] 

$href_regex ="<";            // 1 start of the tag 
$href_regex .="\s*";         // 2 zero or more whitespace 
$href_regex .="a";           // 3 the a of the <a> tag itself 
$href_regex .="\s+";         // 4 one or more whitespace 
$href_regex .="[^>]*";       // 5 zero or more of any character that is _not_ the end of the tag 
$href_regex .="href";        // 6 the href bit of the tag 
$href_regex .="\s*";         // 7 zero or more whitespace 
$href_regex .="=";           // 8 the = of the tag 
$href_regex .="\s*";         // 9 zero or more whitespace 
$href_regex .="[\"']?";      // 10 none or one of " or ' 
$href_regex .="(";           // 11 opening parenthesis, start of the bit we want to capture 
$href_regex .="[^\"' >]+";   // 12 one or more of any character _except_ our closing characters 
$href_regex .=")";           // 13 closing parenthesis, end of the bit we want to capture 
$href_regex .="[\"' >]";     // 14 closing chartacters of the bit we want to capture 

$regex  = "/";         // regex start delimiter 
$regex .= $href_regex; // 
$regex .= "/";         // regex end delimiter 
$regex .= "i";         // Pattern Modifier - makes regex case insensative 
$regex .= "s";         // Pattern Modifier - makes a dot metacharater in the pattern 
                       // match all characters, including newlines 
$regex .= "U";         // Pattern Modifier - makes the regex ungready 

// get the last file we nabbed (AV)
$cwd = getcwd();
$lastDefFile = "{$cwd}/lastdef.txt";
if (file_exists($lastDefFile)) {
  $handle = fopen($lastDefFile, "r");
  while (!feof($handle)) {
    $prevDefFile .= fread($handle, 8192);
  }
  fclose($handle);
}

// get the symantec virus defs content
$handle = fopen("http://securityresponse.symantec.com/avcenter/download/pages/US-N95.html", "r");
$vdefhtml = "";
while (!feof($handle)) {
  $vdefhtml .= fread($handle, 8192);
}
fclose($handle);

// grab all the links from the symantec html page
if (preg_match_all($regex, $vdefhtml, $links)) {
  // go through all the links looking for the right one
  for ($i=0; $i<sizeof($links[1]); $i++) {
    // if the url has i32.exe in it, it is the one we are looking for
    if (strpos($links[1][$i],"i32.exe") !== false) {
      // get the AV definition exe url and file name
      $defFileURL = trim($links[1][$i]);
      $defFile = basename($defFileURL);
      break;
    }
  }
  // if the def file from symantec's html code and the local file match
  // then exit since we already grabbed that file
  if ($prevDefFile == $defFile) {
    exit;
  } else {
    // if the def just happens to exist, delete it
    $tmpfile = "{$defFileTemp}/{$defFile}";
    if (file_exists($tmpfile)) {
      if (unlink($tmpfile) == false) { die("ERROR: failed to delete $tmpfile"); }
    }
	
    // download the AV definition exe file
    $handle1 = @fopen($defFileURL, "rb");
    if (!$handle1) { die("ERROR: failed to open $defFileURL"); }
    $handle2 = @fopen($tmpfile, "w+b");
    if (!$handle2) { die("ERROR: failed to open $tmpfile"); }
    while (!feof($handle1)) {
      // read the remote file
      $avExeFileChunk = fread($handle1, 8192);
      // write the file chunk to the hard drive
      fwrite($handle2, $avExeFileChunk);
    }
    // close the output file and input file
    fclose($handle2);
    fclose($handle1);
	
    // move the av def exe to the shared location
    $tmpfile = "{$defFileTemp}/{$defFile}";
    $newfile = "{$defFileDest}/{$defFile}";
    if (file_exists($newfile)) { 
      unlink($newfile);
      rename($tmpfile, $newfile);
    } else {
      rename($tmpfile, $newfile);
    }
	
    // kill the old av file to conserve space
    if ($prevDefFile != "") {
      $oldfile = "{$defFileDest}/{$prevDefFile}";
      unlink($oldfile);
    }
	
    // update the last file downloaded file (AV)
    $handle = fopen($lastDefFile, "w+");
    fwrite($handle, $defFile);
    fclose($handle);
	
    // shoot out an email to everyone
    // (comment out the line below if you don't want to send notifications)
    sendDefAlertEmail();
  }
} 

function sendDefAlertEmail() {
  global $defFile;

  // include the mailer script (edit this to your location of PHPMailer)
  require("phpmailer/class.phpmailer.php");
  $mail = new PHPMailer();

  $cwd = getcwd();
  $rcptFile = "{$cwd}/recipients.txt";
  
  // load all recipients from text file
  if (file_exists($rcptFile)) {
    $recipients = file($rcptFile);

    $mail->IsSMTP();		// set mailer to use SMTP
    $mail->Host = $smtpHost;	// specify main and backup server
//    $mail->SMTPAuth = true;            // turn on SMTP authentication
//    $mail->Username = "";              // SMTP username
//    $mail->Password = "";              // SMTP password

    $mail->From = $fromEmail;
    $mail->FromName = "";
    // build recipient list
    for ($i=0; $i<sizeof($recipients); $i++) {       // add the to address(es)
      $mailto_address = trim($recipients[$i]);
      if ($mailto_address != "") { $mail->AddAddress($mailto_address); }
    }
    // set some vars
    $mail->IsHTML(true);
//    $mail->WordWrap = 100;                                 // set word wrap to 100 characters
    $mail->Subject = "Employees: Update Your Anti-Virus Definition";
    $mail->Body    = 
"
<html>
<head>
<title>Employees: Update Your Anti-Virus Definition</title>
</head>
<body>
<font size=\"2\" face=\"Verdana, Arial, Helvetica, sans-serif\">
<p>To: All Employees</p>
<p>A new Anti-Virus definition is available.<br>
  Please install this <strong>ASAP</strong> to keep your virus protection up to 
  date.</p>
<p>Click on this link <a href=\"Z:\\Virus Defs\\".$defFile."\">Z:\Virus Defs\\".$defFile."</a> 
  to start the installation.</p>
<p><u>Instructions</u><br>
 1. Click the link above to start the virus definition update<br>
 2. Click the <strong>OPEN</strong> button to download the virus definition update<br>
 3. If prompted, click <strong>YES</strong> to the security warning window<br>
 4. Click <strong>YES</strong> to the SARC Intelligent Updater window<br>
 5. Click <strong>OK</strong> to complete the update</p>
<p><strong><font color=\"#FF0000\">Please be patient throughout the installation process.</font></strong></p>
<p>Thank you,</p>
<p>The Management</p>
</font> 
</body>
</html>
";

    if(!$mail->Send()) {
      die("The message could not be sent.\nMailer Error: ".$mail->ErrorInfo);
    }
    // clean up
    $mail->ClearAllRecipients();
    $mail->SmtpClose();  
  } else {
    die("ERROR: Recipients file could not be found");
  }
}
?>    


How would you rate the usefulness of this content?

Poor 1
2
3
4
5
6
7
8
9
Outstanding

Optional: Tell us why you rated the content this way.
Characters remaining: 1024
Average rating: 4.72 out of 9.

1 2 3 4 5 6 7 8 9
29 people have rated this content.
This page has been viewed 4,096 times
Copyright © 2004-2010 XenoCafe. All Rights Reserved. XenoCafe is Powered by Linux. Free your mind and your wallet. Switch to Linux.