Subversion Repositories DevTools

Rev

Rev 1684 | Blame | Compare with Previous | Last modification | View Log | RSS feed

########################################################################
# Copyright (C) 2010 Vix-ERG Limited, All rights reserved
#
# Module name   : ZendGuard.pl
# Module type   : Makefile system
# Compiler(s)   : Perl
# Environment(s): jats
#
# Description   : See: TECHGP-00254 Jats Integration of ZendGuard

#                 JATS wrapper to invoke the ZendGuard GuardEngine
#                 to process a directory of PHP files.
#
#                 Several assumptions
#
#                 ZendGaurd 5.5 is installed.
#
#                 EnvVars used:
#                   PROGRAMFILES            - Windows 'Program Files'
#                   ZENDGUARD_5_5           - Alternate install location
#                   ZENDGUARD_IGNORE        - Comma sep list of errors to ignore
#
#                 GuardEngine generates a 99 error for no license
#                 Need to test all of this against a valid copy
#
#                 Will be invoked from a JATS makefile at 'make' time
#                 This is not a stand alone utility. Its designed to be
#                 driven from the Jats Directive: MakeZendGuard(...)
#
#                 The guard.xml file conatins all that is needed.
#                 The format of the file MUST
#
#                   Have a targetDir attribute
#
#                   Global variable called RootDir
#
#                   All source paths referenced from RootDir
#
#                 Notes on the guard.xml file
#                 The order of the source directives is important
#                 Copy-as-is operations are order sensitive
#                 They need to be done AFTER the bulk encode operations
#
#......................................................................#

require 5.008_002;
use strict;
use warnings;

use Pod::Usage;
use Getopt::Long;
use File::Path;

use JatsError;
use FileUtils;
use JatsSystem;

#
#   Option Values
#
my $opt_verbose = 0;
my $opt_clean;
my $opt_pkgdir;
my $opt_target;
my $opt_type;
my $opt_script;
my $opt_objdir;
my $opt_bindir;
my $opt_srcdir = '.';
my $opt_pkg = '';

#
#   Globals
#
my $workfile;
my $logfile;
my $outpath;
my $no_license_error = 99;      # Note: Only tested on a system without a license


#-------------------------------------------------------------------------------
# Function        : Main entry point
#
# Description     : Parse user arguments
#                   Generate metrics
#
# Inputs          : None
#
# Returns         : Error code
#

my $result = GetOptions (
                "verbose:+"     => \$opt_verbose,           # flag, multiple use allowed
                "clean"         => \$opt_clean,
                "PackageDir:s"  => \$opt_pkgdir,
                "Target:s"      => \$opt_target,
                "Type:s"        => \$opt_type,
                "script:s"      => \$opt_script,
                "ObjDir:s"      => \$opt_objdir,
                "BinDir:s"      => \$opt_bindir,
                "Src:s"         => \$opt_srcdir,
                "Package:s"     => \$opt_pkg,
                );

                #
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
                #

ErrorConfig( 'name'    =>'ZendGuard',
             'verbose' => $opt_verbose,
            );
Error ("Internal: Invalid options passed")
    unless ($result);

#
#   Determine output path
#   If --Package has been specified then it will be within the package
#   Otherwise it will be created locally to allow it to be consumed by
#   an installer
#
if ( $opt_pkg ) {
    $outpath = join( '/', $opt_pkgdir, 'pkg' ,$opt_pkg );
} else {
    $outpath = join( '/', $opt_bindir, 'php' );
}

#
#   Sanity tests and calculated paths
#
Error ("No script provided") unless ($opt_script);
Error ("No Packaging directory provided") unless ($opt_pkgdir);
Error ("No Bindir directory provided") unless ($opt_bindir);
Error ("Packaging subdirectory cannot have relative path component: $opt_pkg")
    if ( $opt_pkg && $opt_pkg =~ m~\.\./~ );

#
#   Calc values
#
$workfile = join( '/', $opt_objdir, 'GuardEngine.xml' );
$logfile  = join( '/', $opt_objdir, 'GuardEngine.log' );

#
#   Process Clean operations
#   Delete every thingwe create
#
if ( $opt_clean )
{
    Message ("Cleaning: $workfile, $logfile");
    RmDirTree( $workfile );
    RmDirTree( $logfile );
    Message ("Cleaning: $outpath");
    RmDirTree( $outpath );
    exit 0;
}

#
#   Not cleaning
#   Perform a little bit ore sanity testing
#
Verbose("Script : $opt_script");
Verbose("Target : $opt_target");
Verbose("LogFile: $logfile");
Verbose("SrcDir : $opt_srcdir");
Verbose("WrkDir : $opt_objdir");
Verbose("OutDir : $outpath");

Error ("Script not found: $opt_script") unless (-f $opt_script);
Error ("Work directory not found") unless (-d $opt_objdir);

#
#   Ensure that the required version of ZendGaurd can be found
#       Try User EnvVar ZENDGUARD_5_5
#       Else Default install location
#
my $guard5_env_path = $ENV{ZENDGUARD_5_5} || '';
my $default_guard5_path = $ENV{'PROGRAMFILES'} . '/Zend/Zend Guard - 5.5.0';
my $guardengine_path = $guard5_env_path || $default_guard5_path;
$guardengine_path =~ tr~\\~/~s;
Verbose ("GuardPath: $guardengine_path");
if ( ! -d $guardengine_path )
{
    Error( "ZendGuard not installed",
           "Zendguard tools requires that Version 5.5 of ZendGard be installed.",
           "Non default installation may be configured via EnvVar",
           "EnvVar ZENDGUARD_5_5: $guard5_env_path",
           "Default Path: $default_guard5_path");

}

#
#   Now get the subdir for the guard executable
#
$guardengine_path .= '/plugins/com.zend.guard.core.resources.win32.x86_5.5.0/resources';
Error ("Plugin directory not found", $guardengine_path) unless ( -d $guardengine_path );

$guardengine_path .= '/GuardEngine.exe';
Error ("Guard Engine not found", $guardengine_path) unless ( -f $guardengine_path );
Verbose2 ("GuardEngine: $guardengine_path");

#
#   Convert some paths to absolute paths
#   ZendGuard does appear to be worried about the use of '/' intead of '\'
#   My guess is that its happy with both - so use / as its easier
#
InitFileUtils();
$outpath = FullPath($outpath);
$opt_srcdir = FullPath($opt_srcdir);

#
#   Process the script file. Need to:
#       1) set the output directory
#       2) Set source directories
#       3) Capture unexpected styles
#
#   The script is an XML file, but parsing it as an XML file and then
#   reconstructing the file is hard work. Would need to know all about the xsd
#   of the file too.
#
#   Try the simple approach first
#   Asume lines are well formed and not split
#
my @bad_paths;
my $root_dir_seen;
open (my $out,'>', $workfile )    || Error ("Can't open output: $workfile. $!");
open (my $in, '<', $opt_script ) || Error ("Can't open input: $opt_script: $!");
while ( <$in> )
{
    #
    #   Chomp white space at the end of the line
    #   Remove unix and windows lined endings
    #
    s~\s+$~~;

    #
    #   Target Dir
    #   Force to be the output directory
    #
    if ( m~(targetDir=")(.*?)(")~ )
    {
        Verbose("TargetDir: $2");
        s~(targetDir=")(.*?)(")~$1$outpath$3~;
    }

    #
    #   Source Path directives
    #   Must start with $(RootDir)
    #
    if ( m~<source path="(.*?)">~  )
    {
        Verbose("PATH: $1");
        if ( $1 !~ m~^\$\(RootDir\)~ )
        {
            push @bad_paths, $_;
        }
    }

    #
    #   Global Variables
    #   Only interested in RootDir
    #
    #
    if ( m~<variable name="(.*?)">(.*?)</variable>~ )
    {
        Verbose("Variable: $1, $2");
        if ( $1 eq 'RootDir' )
        {
            s~(<variable name=".*?">).*?(</variable>)~$1$opt_srcdir$2~;
            $root_dir_seen = 1;
        }
    }

    #
    #   Output the modified line
    #
    print $out $_ . "\n";
}
close $in;
close $out;

#
#   Report any error that were seen during the file re-write
#
ReportError("Expected a global variables called 'RootDir'", "Not was seen")
    unless ( $root_dir_seen  );

ReportError('The source paths must be specified relative to $(RootDir)',
            'The following elements did not have relative references',
            @bad_paths ) if (@bad_paths );
ErrorDoExit();


#
#   Create the target directory
#
Verbose2("Create packing path: $outpath");
mkpath ( $outpath );
RmDirTree( $logfile );

#
#   Run the required program
#
my $rv = System ('--NoExit','--Shell' ,$guardengine_path, '--xml-file', $workfile, "2>$logfile" );

#
#   Dump the log file if required
#
System ('cat', $logfile ) if ( ($rv && $rv != $no_license_error) || IsVerbose(2) );

#
#   Error reported
#   See if we allow this error
#
if ( $rv )
{
    Warning( '-' x 80, 'Licence may have expired', '-' x 80) if ( $rv == $no_license_error );
    my $elist = $ENV{ZENDGUARD_IGNORE} || '';
    if ( grep ($rv eq $_, split(/,/,$elist)) )
    {
        Warning("GaurdEngine error ignored: $rv");
    }
    else
    {
        Error ("GuardEngine error previously reported: $rv");
    }
}


Message ("Done");
1;