Apache-PAR

 view release on metacpan or  search on metacpan

PAR.pm  view on Meta::CPAN


}

sub unpack_par {
	my $class = shift;
	my($par, $tmpdir) = @_;

	require File::Spec;
	require File::Path;
	require Digest::MD5;

	warn "[PAR] unpacking '$par'\n" if DEBUG;
	my $zip = Archive::Zip->new;
	my $rv = $zip->read($par);
	unless($rv == AZ_OK) {
		 print STDERR "Unable to read ZIP file '$par': error code $rv";
		 return undef;
	}

	$tmpdir ||= File::Spec->tmpdir;
	unless($tmpdir) {
		 print STDERR "no temp directory specified";
		 return undef;
	}
	
	unless(-d $tmpdir) {
		 print STDERR "temp dir '$tmpdir' does not exist or is not a directory";
		 return undef;
	}

	my $tmppar = File::Spec->catdir($tmpdir, 'par', (File::Spec->splitpath($par))[1,2]);
	# Instead of using full path, this will append MD5
	# my $fh;
	# unless(open $fh, '<', $par) {
	# 	 print STDERR "unable to read '$par': $!";
	# 	 return undef;
	# }
	# binmode($fh);
	# my $md5    = Digest::MD5->new->addfile($fh)->hexdigest;
	# my $tmppar = File::Spec->catdir($tmpdir, 'par', $md5);
	# close($fh);

	warn "[PAR] unpack dir is '$tmppar'\n" if DEBUG;

    # mtime check for if MD5 approach isn't used
	if (-d $tmppar) {
		if (DEBUG) {
			warn "[PAR] archive has been unpacked previously\n";
			warn "[PAR] directory age: ", -M $tmppar, "\n";
			warn "[PAR] archive age: ", -M $par, "\n";
		}
		return $tmppar if (stat($tmppar))[9] > (stat($par))[9];
		warn "[PAR] removing old unpack dir '$tmppar'" if DEBUG;
		File::Path::rmtree $tmppar;
	}
 
	# XXX Add signature check here

	# unpack the files
	foreach my $member ($zip->members) {
		# $member->fileName is always in Unix format
		# See also Archive::Zip::_asLocalName()
		my $file = File::Spec->catfile($tmppar, split('/', $member->fileName));
		warn "[PAR] extracting '$file'\n" if DEBUG;
		my $rv = $member->extractToFileNamed($file);
		unless($rv == AZ_OK) {
			 print STDERR "Error extracting '$file' from '$par': error code: $rv";
			 return undef;
		}
		if ($member->fileAttributeFormat == 3) { # unix permissions
			my $perms = $member->unixFileAttributes & 0xFFF;
			unless(chmod $perms, $file) {
				 print STDERR "chmod $perms, $file failed: $!";
				 return undef;
			}
		}
	}

	return $tmppar;
}

import(__PACKAGE__,@pardir,@parfiles,@parloc);

1;
__END__

=head1 NAME

Apache::PAR - Perl extension for including Perl ARchive files in a mod_perl (1.x or 2.x) 
environment.

=head1 SYNOPSIS

  Inside Apache configuration:
    PerlSetVar PARInclude /path/to/par/archive/directory
    ...
    PerlAddVar PARInclude /path/to/a/par/file.par
    ...
    PerlModule Apache::PAR

  In Apache/mod_perl 1.x environments on Win32 platforms, the following 
  should be used instead:
  
    PerlSetVar PARInclude /path/to/par/archive/directory
    ...
    PerlSetVar PARInclude /path/to/a/par/file.par
    ...
    <PERL>
    use Apache::PAR;
    </PERL>


  Alternative configuration, inside a startup.pl script or PERL section:
    use Apache::PAR qw(
      /path/to/par/archive/directory
      /path/to/a/par/file.par
    );

  Inside a web.conf file:

    Alias /myapp/static/ ##PARFILE##/
    <Location /myapp/static>
      SetHandler perl-script
      PerlHandler Apache::PAR::Static
      PerlSetVar PARStaticDirectoryIndex index.htm
      PerlAddVar PARStaticDirectoryIndex index.html
      PerlSetVar PARStaticDefaultMIME text/html
    </Location>

    Alias /myapp/cgi-perl/ ##PARFILE##/
    <Location /myapp/cgi-perl>

PAR.pm  view on Meta::CPAN


=item * If PerlInitHandler Apache::PAR is specified, and the contents of a PAR file change, 
the archive will be reloaded (modules and content.)

=back

=head2 Some things to note:

PerlSetVar/AddVar configuration for PARInclude and PARTempDir B<MUST> be before the 
PerlModule Apache::PAR (or use Apache::PAR;) line in the Apache configuration.  
Any PARInclude variables (or PARDir and PARFile) after the PerlModule line will be ignored.

PARDir and PARFile directives may be used to specify the location of PAR archives, however 
their use is deprecated.  For new configurations, use PARInclude instead.  PARInclude works 
both as PARDir and PARFile by first expanding directories to include any PAR archives found 
within.

The arguments for PARInclude can be either an absolute path, or a relative path from Apache's 
server_root.  For example, if your Apache's server_root is /usr/local/apache, and you would 
like to load .par files from a parfiles/ subdirectory, use:
  PerlSetVar PARInclude parfiles/

This will then look for .par files in the /usr/local/apache/parfiles directory.

The name of the configuration file which is loaded is configurable via PARConf 
(default is 'web.conf'.)  For example, to set the include filename to 'include.conf' for 
all .par files:
  PerlSetVar PARConf include.conf

The extensions used when searching for .par archives in any directories set via PARInclude 
is set using the PARExt variable in the Apache configuration (the default is 'par').  
For example, to set the par extension to 'zip':
  PerlSetVar PARExt zip

There is currently no way to limit which .par archive a module is loaded out of.  To ensure 
that the correct module is being loaded, I suggest the following convention: begin module 
names with the name of the archive.  For instance, a MailForm module within the MyApp.par 
archive should be named MyApp::MailForm

Currently, which directory inside a .par archive modules are loaded out of is not 
configurable, and is the same as defined in PAR.pm:

=over 4

=item 1. /

=item 2. /lib/

=item 3. /arch/

=item 4. /i386-freebsd/       # i.e. $Config{archname}

=item 5. /5.8.0/              # i.e. $Config{version}

=item 6. /5.8.0/i386-freebsd/ # both of the above

=back

By default, if a web.conf file contains a C<##UNPACKDIR##> directive, the archive will be 
unpacked to a subdirectory under PARTempDir during Apache startup.  The default for 
PARTempDir is the platform specific temp directory (e.g. c:\temp for win32, /tmp for *nix.)
Archive unpacking may be disabled by specifying C<PerlSetVar PARTempDir NONE> in the Apache 
configuration, however this will prevent the loading of any PAR files which require 
unpacking to operate.

Changed content in PAR files is not reloaded util the next restart of Apache unless the 
directive C<PerlInitHandler Apache::PAR> is used.  Currently, some functionality will not 
change or reload when a PAR file is removed, however.  This may change in a future release.

=head1 PLATFORM SPECIFIC

In general, Apache::PAR should function on most platforms without changes, as it is 
(currently) a perl only module.  Below are notes for any known exceptions.  If you have 
any problems with Apache::PAR on your platform, please contact me through one of the 
methods in the CONTACT section.

=head2 Windows 32 bit

Some testing has been performed on Apache::PAR using WIN32 platforms, with both 
mod_perl 1.x and 2.x.  Apache::PAR should function as normal on these platforms, however, 
an alternate configuration method is required due to differences in the Apache/mod_perl 
startup sequence on that platform.

inside a PERL section or startup.pl:

    use Apache::PAR qw(
      /path/to/par/archive/directory
      /path/to/a/par/file.par
      ...
    );

Additionally, you can still use PerlSetVar PARInclude, etc lines in Win32 - the 
Apache::PAR include must be via a use however (not a PerlModule directive):

inside httpd.conf (example for mod_perl 1.x, for 2.x use <PERL > instead):

  PerlSetVar PerlInclude /path/to/par/archive/directory
  PerlAddVar PerlInclude /path/to/a/par/file.par
  ...
  <PERL>
    use Apache::PAR;
  </PERL>

=head1 EXPORT

None by default.

=head1 ACKNOWLEDGEMENTS

Autrijus Tang E<lt>autrijus@autrijus.orgE<gt> for providing assistance on numerous 
occasions during the development of Apache::PAR.

Maurice Aubrey E<lt>maurice@lovelyfilth.comE<gt> for adding the ability to unpack content 
from PAR archives.

=head1 CONTACT

For questions regarding the installation or use of Apache::PAR, either post a message on 
the PAR list E<lt>par@perl.orgE<gt>, on the sourceforge project page at 
L<http://www.sourceforge.net/projects/apache-par> or send an email to the author directly 
at E<lt>nathan@byrd.netE<gt>.



( run in 1.975 second using v1.01-cache-2.11-cpan-99c4e6809bf )