Commit bfa7bf91 authored by root's avatar root

major update

parent d23e8d47
# $Id: CheckLib.pm,v 1.25 2008/10/27 12:16:23 drhyde Exp $
package Devel::CheckLib;
use 5.00405; #postfix foreach
use strict;
use vars qw($VERSION @ISA @EXPORT);
$VERSION = '1.10';
use Config qw(%Config);
use Text::ParseWords 'quotewords';
use File::Spec;
use File::Temp;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(assert_lib check_lib_or_exit check_lib);
# localising prevents the warningness leaking out of this module
local $^W = 1; # use warnings is a 5.6-ism
_findcc(); # bomb out early if there's no compiler
=head1 NAME
Devel::CheckLib - check that a library is available
=head1 DESCRIPTION
Devel::CheckLib is a perl module that checks whether a particular C
library and its headers are available.
=head1 SYNOPSIS
use Devel::CheckLib;
check_lib_or_exit( lib => 'jpeg', header => 'jpeglib.h' );
check_lib_or_exit( lib => [ 'iconv', 'jpeg' ] );
# or prompt for path to library and then do this:
check_lib_or_exit( lib => 'jpeg', libpath => $additional_path );
=head1 USING IT IN Makefile.PL or Build.PL
If you want to use this from Makefile.PL or Build.PL, do
not simply copy the module into your distribution as this may cause
problems when PAUSE and search.cpan.org index the distro. Instead, use
the use-devel-checklib script.
=head1 HOW IT WORKS
You pass named parameters to a function, describing to it how to build
and link to the libraries.
It works by trying to compile some code - which defaults to this:
int main(int argc, char *argv[]) { return 0; }
and linking it to the specified libraries. If something pops out the end
which looks executable, it gets executed, and if main() returns 0 we know
that it worked. That tiny program is
built once for each library that you specify, and (without linking) once
for each header file.
If you want to check for the presence of particular functions in a
library, or even that those functions return particular results, then
you can pass your own function body for main() thus:
check_lib_or_exit(
function => 'foo();if(libversion() > 5) return 0; else return 1;'
incpath => ...
libpath => ...
lib => ...
header => ...
);
In that case, it will fail to build if either foo() or libversion() don't
exist, and main() will return the wrong value if libversion()'s return
value isn't what you want.
=head1 FUNCTIONS
All of these take the same named parameters and are exported by default.
To avoid exporting them, C<use Devel::CheckLib ()>.
=head2 assert_lib
This takes several named parameters, all of which are optional, and dies
with an error message if any of the libraries listed can
not be found. B<Note>: dying in a Makefile.PL or Build.PL may provoke
a 'FAIL' report from CPAN Testers' automated smoke testers. Use
C<check_lib_or_exit> instead.
The named parameters are:
=over
=item lib
Must be either a string with the name of a single
library or a reference to an array of strings of library names. Depending
on the compiler found, library names will be fed to the compiler either as
C<-l> arguments or as C<.lib> file names. (E.g. C<-ljpeg> or C<jpeg.lib>)
=item libpath
a string or an array of strings
representing additional paths to search for libraries.
=item LIBS
a C<ExtUtils::MakeMaker>-style space-separated list of
libraries (each preceded by '-l') and directories (preceded by '-L').
This can also be supplied on the command-line.
=item debug
If true - emit information during processing that can be used for
debugging.
=back
And libraries are no use without header files, so ...
=over
=item header
Must be either a string with the name of a single
header file or a reference to an array of strings of header file names.
=item incpath
a string or an array of strings
representing additional paths to search for headers.
=item INC
a C<ExtUtils::MakeMaker>-style space-separated list of
incpaths, each preceded by '-I'.
This can also be supplied on the command-line.
=item ccflags
Extra flags to pass to the compiler.
=item ldflags
Extra flags to pass to the linker.
=item analyze_binary
a callback function that will be invoked in order to perform custom
analysis of the generated binary. The callback arguments are the
library name and the path to the binary just compiled.
It is possible to use this callback, for instance, to inspect the
binary for further dependencies.
=back
=head2 check_lib_or_exit
This behaves exactly the same as C<assert_lib()> except that instead of
dieing, it warns (with exactly the same error message) and exits.
This is intended for use in Makefile.PL / Build.PL
when you might want to prompt the user for various paths and
things before checking that what they've told you is sane.
If any library or header is missing, it exits with an exit value of 0 to avoid
causing a CPAN Testers 'FAIL' report. CPAN Testers should ignore this
result -- which is what you want if an external library dependency is not
available.
=head2 check_lib
This behaves exactly the same as C<assert_lib()> except that it is silent,
returning false instead of dieing, or true otherwise.
=cut
sub check_lib_or_exit {
eval 'assert_lib(@_)';
if($@) {
warn $@;
exit;
}
}
sub check_lib {
eval 'assert_lib(@_)';
return $@ ? 0 : 1;
}
# borrowed from Text::ParseWords
sub _parse_line {
my($delimiter, $keep, $line) = @_;
my($word, @pieces);
no warnings 'uninitialized'; # we will be testing undef strings
while (length($line)) {
# This pattern is optimised to be stack conservative on older perls.
# Do not refactor without being careful and testing it on very long strings.
# See Perl bug #42980 for an example of a stack busting input.
$line =~ s/^
(?:
# double quoted string
(") # $quote
((?>[^\\"]*(?:\\.[^\\"]*)*))" # $quoted
| # --OR--
# singe quoted string
(') # $quote
((?>[^\\']*(?:\\.[^\\']*)*))' # $quoted
| # --OR--
# unquoted string
( # $unquoted
(?:\\.|[^\\"'])*?
)
# followed by
( # $delim
\Z(?!\n) # EOL
| # --OR--
(?-x:$delimiter) # delimiter
| # --OR--
(?!^)(?=["']) # a quote
)
)//xs or return; # extended layout
my ($quote, $quoted, $unquoted, $delim) = (($1 ? ($1,$2) : ($3,$4)), $5, $6);
return() unless( defined($quote) || length($unquoted) || length($delim));
if ($keep) {
$quoted = "$quote$quoted$quote";
}
else {
$unquoted =~ s/\\(.)/$1/sg;
if (defined $quote) {
$quoted =~ s/\\(.)/$1/sg if ($quote eq '"');
}
}
$word .= substr($line, 0, 0); # leave results tainted
$word .= defined $quote ? $quoted : $unquoted;
if (length($delim)) {
push(@pieces, $word);
push(@pieces, $delim) if ($keep eq 'delimiters');
undef $word;
}
if (!length($line)) {
push(@pieces, $word);
}
}
return(@pieces);
}
sub assert_lib {
my %args = @_;
my (@libs, @libpaths, @headers, @incpaths);
# FIXME: these four just SCREAM "refactor" at me
@libs = (ref($args{lib}) ? @{$args{lib}} : $args{lib})
if $args{lib};
@libpaths = (ref($args{libpath}) ? @{$args{libpath}} : $args{libpath})
if $args{libpath};
@headers = (ref($args{header}) ? @{$args{header}} : $args{header})
if $args{header};
@incpaths = (ref($args{incpath}) ? @{$args{incpath}} : $args{incpath})
if $args{incpath};
my $analyze_binary = $args{analyze_binary};
my @argv = @ARGV;
push @argv, _parse_line('\s+', 0, $ENV{PERL_MM_OPT}||'');
# work-a-like for Makefile.PL's LIBS and INC arguments
# if given as command-line argument, append to %args
for my $arg (@argv) {
for my $mm_attr_key (qw(LIBS INC)) {
if (my ($mm_attr_value) = $arg =~ /\A $mm_attr_key = (.*)/x) {
# it is tempting to put some \s* into the expression, but the
# MM command-line parser only accepts LIBS etc. followed by =,
# so we should not be any more lenient with whitespace than that
$args{$mm_attr_key} .= " $mm_attr_value";
}
}
}
use Data::Dumper qw(Dumper);
# using special form of split to trim whitespace
if(defined($args{LIBS})) {
foreach my $arg (ref $args{LIBS} eq "ARRAY" ? @{$args{LIBS}} : split(' ', $args{LIBS})) {
die("LIBS argument badly-formed: $arg\n") unless($arg =~ /^-[lLR]/);
push @{$arg =~ /^-l/ ? \@libs : \@libpaths}, substr($arg, 2);
}
}
if(defined($args{INC})) {
foreach my $arg (split(' ', $args{INC})) {
die("INC argument badly-formed: $arg\n") unless($arg =~ /^-I/);
push @incpaths, substr($arg, 2);
}
}
my ($cc, $ld) = _findcc($args{debug}, $args{ccflags}, $args{ldflags});
my @missing;
my @wrongresult;
my @wronganalysis;
my @use_headers;
# first figure out which headers we can't find ...
for my $header (@headers) {
push @use_headers, $header;
my($ch, $cfile) = File::Temp::tempfile(
'assertlibXXXXXXXX', SUFFIX => '.c'
);
my $ofile = $cfile;
$ofile =~ s/\.c$/$Config{_o}/;
print $ch qq{#include <$_>\n} for @use_headers;
print $ch qq{int main(void) { return 0; }\n};
close($ch);
my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
my @sys_cmd;
# FIXME: re-factor - almost identical code later when linking
if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
require Win32;
@sys_cmd = (
@$cc,
$cfile,
"/Fe$exefile",
(map { '/I'.Win32::GetShortPathName($_) } @incpaths),
"/link",
@$ld,
split(' ', $Config{libs}),
);
} elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland
@sys_cmd = (
@$cc,
@$ld,
(map { "-I$_" } @incpaths),
"-o$exefile",
$cfile
);
} else { # Unix-ish: gcc, Sun, AIX (gcc, cc), ...
@sys_cmd = (
@$cc,
@$ld,
$cfile,
(map { "-I$_" } @incpaths),
"-o", "$exefile"
);
}
warn "# @sys_cmd\n" if $args{debug};
my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
push @missing, $header if $rv != 0 || ! -x $exefile;
_cleanup_exe($exefile);
unlink $cfile;
}
# now do each library in turn with headers
my($ch, $cfile) = File::Temp::tempfile(
'assertlibXXXXXXXX', SUFFIX => '.c'
);
my $ofile = $cfile;
$ofile =~ s/\.c$/$Config{_o}/;
print $ch qq{#include <$_>\n} foreach (@headers);
print $ch "int main(int argc, char *argv[]) { ".($args{function} || 'return 0;')." }\n";
close($ch);
for my $lib ( @libs ) {
my $exefile = File::Temp::mktemp( 'assertlibXXXXXXXX' ) . $Config{_exe};
my @sys_cmd;
if ( $Config{cc} eq 'cl' ) { # Microsoft compiler
require Win32;
my @libpath = map {
q{/libpath:} . Win32::GetShortPathName($_)
} @libpaths;
# this is horribly sensitive to the order of arguments
@sys_cmd = (
@$cc,
$cfile,
"${lib}.lib",
"/Fe$exefile",
(map { '/I'.Win32::GetShortPathName($_) } @incpaths),
"/link",
@$ld,
split(' ', $Config{libs}),
(map {'/libpath:'.Win32::GetShortPathName($_)} @libpaths),
);
} elsif($Config{cc} eq 'CC/DECC') { # VMS
} elsif($Config{cc} =~ /bcc32(\.exe)?/) { # Borland
@sys_cmd = (
@$cc,
@$ld,
"-o$exefile",
(map { "-I$_" } @incpaths),
(map { "-L$_" } @libpaths),
"-l$lib",
$cfile);
} else { # Unix-ish
# gcc, Sun, AIX (gcc, cc)
@sys_cmd = (
@$cc,
@$ld,
$cfile,
"-o", "$exefile",
(map { "-I$_" } @incpaths),
(map { "-L$_" } @libpaths),
"-l$lib",
);
}
warn "# @sys_cmd\n" if $args{debug};
local $ENV{LD_RUN_PATH} = join(":", @libpaths).":".$ENV{LD_RUN_PATH} unless $^O eq 'MSWin32';
local $ENV{PATH} = join(";", @libpaths).";".$ENV{PATH} if $^O eq 'MSWin32';
my $rv = $args{debug} ? system(@sys_cmd) : _quiet_system(@sys_cmd);
if ($rv != 0 || ! -x $exefile) {
push @missing, $lib;
}
else {
my $absexefile = File::Spec->rel2abs($exefile);
$absexefile = '"'.$absexefile.'"' if $absexefile =~ m/\s/;
if (system($absexefile) != 0) {
push @wrongresult, $lib;
}
else {
if ($analyze_binary) {
push @wronganalysis, $lib if !$analyze_binary->($lib, $exefile)
}
}
}
_cleanup_exe($exefile);
}
unlink $cfile;
my $miss_string = join( q{, }, map { qq{'$_'} } @missing );
die("Can't link/include C library $miss_string, aborting.\n") if @missing;
my $wrong_string = join( q{, }, map { qq{'$_'} } @wrongresult);
die("wrong result: $wrong_string\n") if @wrongresult;
my $analysis_string = join(q{, }, map { qq{'$_'} } @wronganalysis );
die("wrong analysis: $analysis_string") if @wronganalysis;
}
sub _cleanup_exe {
my ($exefile) = @_;
my $ofile = $exefile;
$ofile =~ s/$Config{_exe}$/$Config{_o}/;
# List of files to remove
my @rmfiles;
push @rmfiles, $exefile, $ofile, "$exefile\.manifest";
if ( $Config{cc} eq 'cl' ) {
# MSVC also creates foo.ilk and foo.pdb
my $ilkfile = $exefile;
$ilkfile =~ s/$Config{_exe}$/.ilk/;
my $pdbfile = $exefile;
$pdbfile =~ s/$Config{_exe}$/.pdb/;
push @rmfiles, $ilkfile, $pdbfile;
}
foreach (@rmfiles) {
if ( -f $_ ) {
unlink $_ or warn "Could not remove $_: $!";
}
}
return
}
# return ($cc, $ld)
# where $cc is an array ref of compiler name, compiler flags
# where $ld is an array ref of linker flags
sub _findcc {
my ($debug, $user_ccflags, $user_ldflags) = @_;
# Need to use $keep=1 to work with MSWin32 backslashes and quotes
my $Config_ccflags = $Config{ccflags}; # use copy so ASPerl will compile
my @Config_ldflags = ();
for my $config_val ( @Config{qw(ldflags)} ){
push @Config_ldflags, $config_val if ( $config_val =~ /\S/ );
}
my @ccflags = grep { length } quotewords('\s+', 1, $Config_ccflags||'', $user_ccflags||'');
my @ldflags = grep { length && $_ !~ m/^-Wl/ } quotewords('\s+', 1, @Config_ldflags, $user_ldflags||'');
my @paths = split(/$Config{path_sep}/, $ENV{PATH});
my @cc = split(/\s+/, $Config{cc});
if (check_compiler ($cc[0], $debug)) {
return ( [ @cc, @ccflags ], \@ldflags );
}
# Find the extension for executables.
my $exe = $Config{_exe};
if ($^O eq 'cygwin') {
$exe = '';
}
foreach my $path (@paths) {
# Look for "$path/$cc[0].exe"
my $compiler = File::Spec->catfile($path, $cc[0]) . $exe;
if (check_compiler ($compiler, $debug)) {
return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
}
next if ! $exe;
# Look for "$path/$cc[0]" without the .exe, if necessary.
$compiler = File::Spec->catfile($path, $cc[0]);
if (check_compiler ($compiler, $debug)) {
return ([ $compiler, @cc[1 .. $#cc], @ccflags ], \@ldflags)
}
}
die("Couldn't find your C compiler.\n");
}
sub check_compiler
{
my ($compiler, $debug) = @_;
if (-f $compiler && -x $compiler) {
if ($debug) {
warn("# Compiler seems to be $compiler\n");
}
return 1;
}
return '';
}
# code substantially borrowed from IPC::Run3
sub _quiet_system {
my (@cmd) = @_;
# save handles
local *STDOUT_SAVE;
local *STDERR_SAVE;
open STDOUT_SAVE, ">&STDOUT" or die "CheckLib: $! saving STDOUT";
open STDERR_SAVE, ">&STDERR" or die "CheckLib: $! saving STDERR";
# redirect to nowhere
local *DEV_NULL;
open DEV_NULL, ">" . File::Spec->devnull
or die "CheckLib: $! opening handle to null device";
open STDOUT, ">&" . fileno DEV_NULL
or die "CheckLib: $! redirecting STDOUT to null handle";
open STDERR, ">&" . fileno DEV_NULL
or die "CheckLib: $! redirecting STDERR to null handle";
# run system command
my $rv = system(@cmd);
# restore handles
open STDOUT, ">&" . fileno STDOUT_SAVE
or die "CheckLib: $! restoring STDOUT handle";
open STDERR, ">&" . fileno STDERR_SAVE
or die "CheckLib: $! restoring STDERR handle";
return $rv;
}
=head1 PLATFORMS SUPPORTED
You must have a C compiler installed. We check for C<$Config{cc}>,
both literally as it is in Config.pm and also in the $PATH.
It has been tested with varying degrees of rigorousness on:
=over
=item gcc (on Linux, *BSD, Mac OS X, Solaris, Cygwin)
=item Sun's compiler tools on Solaris
=item IBM's tools on AIX
=item SGI's tools on Irix 6.5
=item Microsoft's tools on Windows
=item MinGW on Windows (with Strawberry Perl)
=item Borland's tools on Windows
=item QNX
=back
=head1 WARNINGS, BUGS and FEEDBACK
This is a very early release intended primarily for feedback from
people who have discussed it. The interface may change and it has
not been adequately tested.
Feedback is most welcome, including constructive criticism.
Bug reports should be made using L<http://rt.cpan.org/> or by email.
When submitting a bug report, please include the output from running:
perl -V
perl -MDevel::CheckLib -e0
=head1 SEE ALSO
L<Devel::CheckOS>
L<Probe::Perl>
=head1 AUTHORS
David Cantrell E<lt>david@cantrell.org.ukE<gt>
David Golden E<lt>dagolden@cpan.orgE<gt>
Yasuhiro Matsumoto E<lt>mattn@cpan.orgE<gt>
Thanks to the cpan-testers-discuss mailing list for prompting us to write it
in the first place;
to Chris Williams for help with Borland support;
to Tony Cook for help with Microsoft compiler command-line options
=head1 COPYRIGHT and LICENCE
Copyright 2007 David Cantrell. Portions copyright 2007 David Golden.
This module is free-as-in-speech software, and may be used, distributed,
and modified under the same conditions as perl itself.
=head1 CONSPIRACY
This module is also free-as-in-mason software.
=cut
1;
Imager::File::PNG 0.99|--configure-args="--libpath=/opt/thirdlane/perl_lib/local/usr/lib --incpath=/opt/thirdlane/perl_lib/local/usr/include"
#!/usr/bin/perl #!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
if 0; # not running under some shell
use strict; use strict;
use Module::Build 0.25; use Module::Build 0.25;
use Getopt::Long; use Getopt::Long;
......
#!/usr/bin/perl #!/usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
if 0; # not running under some shell
# Time-stamp: "2000-10-02 14:48:15 MDT" # Time-stamp: "2000-10-02 14:48:15 MDT"
# #
# Parse the given HTML file(s) and dump the parse tree # Parse the given HTML file(s) and dump the parse tree
......
...@@ -38,11 +38,11 @@ ExtUtils::Install - install files from here to there ...@@ -38,11 +38,11 @@ ExtUtils::Install - install files from here to there
=head1 VERSION =head1 VERSION
2.06 2.04
=cut =cut
$VERSION = '2.06'; # <-- do not forget to update the POD section just above this line! $VERSION = '2.04'; # <-- do not forget to update the POD section just above this line!
$VERSION = eval $VERSION; $VERSION = eval $VERSION;
=pod =pod
...@@ -101,6 +101,12 @@ my $Is_Win32 = $^O eq 'MSWin32'; ...@@ -101,6 +101,12 @@ my $Is_Win32 = $^O eq 'MSWin32';
my $Is_cygwin = $^O eq 'cygwin'; my $Is_cygwin = $^O eq 'cygwin';
my $CanMoveAtBoot = ($Is_Win32 || $Is_cygwin); my $CanMoveAtBoot = ($Is_Win32 || $Is_cygwin);
# *note* CanMoveAtBoot is only incidentally the same condition as below
# this needs not hold true in the future.
my $Has_Win32API_File = ($Is_Win32 || $Is_cygwin)
? (eval {require Win32API::File; 1} || 0)
: 0;
my $Inc_uninstall_warn_handler; my $Inc_uninstall_warn_handler;
...@@ -167,53 +173,47 @@ If $moan is true then returns 0 on error and warns instead of dies. ...@@ -167,53 +173,47 @@ If $moan is true then returns 0 on error and warns instead of dies.
=cut =cut
{
my $Has_Win32API_File;
sub _move_file_at_boot { #XXX OS-SPECIFIC
my ( $file, $target, $moan )= @_;
Carp::confess("Panic: Can't _move_file_at_boot on this platform!")
unless $CanMoveAtBoot;
my $descr= ref $target
? "'$file' for deletion"
: "'$file' for installation as '$target'";
# *note* CanMoveAtBoot is only incidentally the same condition as below
# this needs not hold true in the future.
$Has_Win32API_File = ($Is_Win32 || $Is_cygwin)
? (eval {require Win32API::File; 1} || 0)
: 0 unless defined $Has_Win32API_File;
if ( ! $Has_Win32API_File ) {
my @msg=(
"Cannot schedule $descr at reboot.",
"Try installing Win32API::File to allow operations on locked files",
"to be scheduled during reboot. Or try to perform the operation by",
"hand yourself. (You may need to close other perl processes first)"
);
if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
return 0;
}
my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT();
$opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING()
unless ref $target;
_chmod( 0666, $file );
_chmod( 0666, $target ) unless ref $target;
if (Win32API::File::MoveFileEx( $file, $target, $opts )) { sub _move_file_at_boot { #XXX OS-SPECIFIC
$MUST_REBOOT ||= ref $target ? 0 : 1; my ( $file, $target, $moan )= @_;
return 1; Carp::confess("Panic: Can't _move_file_at_boot on this platform!")
} else { unless $CanMoveAtBoot;
my @msg=(
"MoveFileEx $descr at reboot failed: $^E", my $descr= ref $target
"You may try to perform the operation by hand yourself. ", ? "'$file' for deletion"
"(You may need to close other perl processes first).", : "'$file' for installation as '$target'";
);
if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) } if ( ! $Has_Win32API_File ) {
}
my @msg=(
"Cannot schedule $descr at reboot.",
"Try installing Win32API::File to allow operations on locked files",
"to be scheduled during reboot. Or try to perform the operation by",
"hand yourself. (You may need to close other perl processes first)"
);
if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
return 0; return 0;
} }
my $opts= Win32API::File::MOVEFILE_DELAY_UNTIL_REBOOT();
$opts= $opts | Win32API::File::MOVEFILE_REPLACE_EXISTING()
unless ref $target;
_chmod( 0666, $file );
_chmod( 0666, $target ) unless ref $target;
if (Win32API::File::MoveFileEx( $file, $target, $opts )) {
$MUST_REBOOT ||= ref $target ? 0 : 1;
return 1;
} else {
my @msg=(
"MoveFileEx $descr at reboot failed: $^E",
"You may try to perform the operation by hand yourself. ",
"(You may need to close other perl processes first).",
);
if ( $moan ) { _warnonce(@msg) } else { _choke(@msg) }
}
return 0;
} }
...@@ -1158,12 +1158,11 @@ sub run_filter { ...@@ -1158,12 +1158,11 @@ sub run_filter {
=item B<pm_to_blib> =item B<pm_to_blib>
pm_to_blib(\%from_to);
pm_to_blib(\%from_to, $autosplit_dir); pm_to_blib(\%from_to, $autosplit_dir);
pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd); pm_to_blib(\%from_to, $autosplit_dir, $filter_cmd);
Copies each key of %from_to to its corresponding value efficiently. Copies each key of %from_to to its corresponding value efficiently.
If an $autosplit_dir is provided, all .pm files will be autosplit into it. Filenames with the extension .pm are autosplit into the $autosplit_dir.
Any destination directories are created. Any destination directories are created.
$filter_cmd is an optional shell command to run each .pm file through $filter_cmd is an optional shell command to run each .pm file through
...@@ -1181,7 +1180,7 @@ environment variable will silence this output. ...@@ -1181,7 +1180,7 @@ environment variable will silence this output.
sub pm_to_blib { sub pm_to_blib {
my($fromto,$autodir,$pm_filter) = @_; my($fromto,$autodir,$pm_filter) = @_;
_mkpath($autodir,0,0755) if defined $autodir; _mkpath($autodir,0,0755);
while(my($from, $to) = each %$fromto) { while(my($from, $to) = each %$fromto) {
if( -f $to && -s $from == -s $to && -M $to < -M $from ) { if( -f $to && -s $from == -s $to && -M $to < -M $from ) {
print "Skip $to (unchanged)\n" unless $INSTALL_QUIET; print "Skip $to (unchanged)\n" unless $INSTALL_QUIET;
...@@ -1217,7 +1216,7 @@ sub pm_to_blib { ...@@ -1217,7 +1216,7 @@ sub pm_to_blib {
utime($atime,$mtime+$Is_VMS,$to); utime($atime,$mtime+$Is_VMS,$to);
_chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to); _chmod(0444 | ( $mode & 0111 ? 0111 : 0 ),$to);
next unless $from =~ /\.pm$/; next unless $from =~ /\.pm$/;
_autosplit($to,$autodir) if defined $autodir; _autosplit($to,$autodir);
} }
} }
......
...@@ -17,7 +17,7 @@ my $DOSISH = ($^O =~ /^(MSWin\d\d|os2|dos|mint)$/); ...@@ -17,7 +17,7 @@ my $DOSISH = ($^O =~ /^(MSWin\d\d|os2|dos|mint)$/);
require VMS::Filespec if $Is_VMS; require VMS::Filespec if $Is_VMS;
use vars qw($VERSION); use vars qw($VERSION);
$VERSION = '2.06'; $VERSION = '2.04';
$VERSION = eval $VERSION; $VERSION = eval $VERSION;
sub _is_prefix { sub _is_prefix {
......
...@@ -5,7 +5,7 @@ use strict; ...@@ -5,7 +5,7 @@ use strict;
use Carp qw(); use Carp qw();
use Config; use Config;
use vars qw($VERSION $Relocations); use vars qw($VERSION $Relocations);
$VERSION = '2.06'; $VERSION = '2.04';
$VERSION = eval $VERSION; $VERSION = eval $VERSION;
# Used for generating filehandle globs. IO::File might not be available! # Used for generating filehandle globs. IO::File might not be available!
......
...@@ -10,18 +10,17 @@ sub config { $config->{$_[1]} } ...@@ -10,18 +10,17 @@ sub config { $config->{$_[1]} }
sub set_config { $config->{$_[1]} = $_[2] } sub set_config { $config->{$_[1]} = $_[2] }
sub set_feature { $features->{$_[1]} = 0+!!$_[2] } # Constrain to 1 or 0 sub set_feature { $features->{$_[1]} = 0+!!$_[2] } # Constrain to 1 or 0
sub auto_feature_names { grep !exists $features->{$_}, keys %$auto_features } sub auto_feature_names { sort grep !exists $features->{$_}, keys %$auto_features }
sub feature_names { sub feature_names {
my @features = (keys %$features, auto_feature_names()); my @features = (sort keys %$features, auto_feature_names());
@features; @features;
} }
sub config_names { keys %$config } sub config_names { sort keys %$config }
sub write { sub write {
my $me = __FILE__; my $me = __FILE__;
require IO::File;
# Can't use Module::Build::Dumper here because M::B is only a # Can't use Module::Build::Dumper here because M::B is only a
# build-time prereq of this module # build-time prereq of this module
...@@ -29,7 +28,7 @@ sub write { ...@@ -29,7 +28,7 @@ sub write {
my $mode_orig = (stat $me)[2] & 07777; my $mode_orig = (stat $me)[2] & 07777;
chmod($mode_orig | 0222, $me); # Make it writeable chmod($mode_orig | 0222, $me); # Make it writeable
my $fh = IO::File->new($me, 'r+') or die "Can't rewrite $me: $!"; open(my $fh, '+<', $me) or die "Can't rewrite $me: $!";
seek($fh, 0, 0); seek($fh, 0, 0);
while (<$fh>) { while (<$fh>) {
last if /^__DATA__$/; last if /^__DATA__$/;
...@@ -38,11 +37,11 @@ sub write { ...@@ -38,11 +37,11 @@ sub write {
seek($fh, tell($fh), 0); seek($fh, tell($fh), 0);
my $data = [$config, $features, $auto_features]; my $data = [$config, $features, $auto_features];
$fh->print( 'do{ my ' print($fh 'do{ my '
. Data::Dumper->new([$data],['x'])->Purity(1)->Dump() . Data::Dumper->new([$data],['x'])->Purity(1)->Dump()
. '$x; }' ); . '$x; }' );
truncate($fh, tell($fh)); truncate($fh, tell($fh));
$fh->close; close $fh;
chmod($mode_orig, $me) chmod($mode_orig, $me)
or warn "Couldn't restore permissions on $me: $!"; or warn "Couldn't restore permissions on $me: $!";
...@@ -54,18 +53,13 @@ sub feature { ...@@ -54,18 +53,13 @@ sub feature {
my $info = $auto_features->{$key} or return 0; my $info = $auto_features->{$key} or return 0;
# Under perl 5.005, each(%$foo) isn't working correctly when $foo
# was reanimated with Data::Dumper and eval(). Not sure why, but
# copying to a new hash seems to solve it.
my %info = %$info;
require Module::Build; # XXX should get rid of this require Module::Build; # XXX should get rid of this
while (my ($type, $prereqs) = each %info) { foreach my $type (sort keys %$info) {
my $prereqs = $info->{$type};
next if $type eq 'description' || $type eq 'recommends'; next if $type eq 'description' || $type eq 'recommends';
my %p = %$prereqs; # Ditto here. foreach my $modname (sort keys %$prereqs) {
while (my ($modname, $spec) = each %p) { my $status = Module::Build->check_installed_status($modname, $prereqs->{$modname});
my $status = Module::Build->check_installed_status($modname, $spec);
if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; } if ((!$status->{ok}) xor ($type =~ /conflicts$/)) { return 0; }
if ( ! eval "require $modname; 1" ) { return 0; } if ( ! eval "require $modname; 1" ) { return 0; }
} }
...@@ -168,45 +162,45 @@ do{ my $x = [ ...@@ -168,45 +162,45 @@ do{ my $x = [
{}, {},
{}, {},
{ {
'manpage_support' => {
'description' => 'Create Unix man pages',
'requires' => {
'Pod::Man' => 0
}
},
'HTML_support' => { 'HTML_support' => {
'description' => 'Create HTML documentation', 'description' => 'Create HTML documentation',
'requires' => { 'requires' => {
'Pod::Html' => 0 'Pod::Html' => 0
} }
}, },
'PPM_support' => {
'description' => 'Generate PPM files for distributions'
},
'dist_authoring' => { 'dist_authoring' => {
'description' => 'Create new distributions',
'recommends' => { 'recommends' => {
'Module::Signature' => '0.21', 'Module::Signature' => '0.21',
'Pod::Readme' => '0.04' 'Pod::Readme' => '0.04'
}, },
'requires' => { 'requires' => {
'Archive::Tar' => '1.09' 'Archive::Tar' => '1.09'
}, }
'description' => 'Create new distributions'
}, },
'license_creation' => {
'description' => 'Create licenses automatically in distributions',
'requires' => {
'Software::License' => '0.103009'
}
},
'inc_bundling_support' => { 'inc_bundling_support' => {
'description' => 'Bundle Module::Build in inc/', 'description' => 'Bundle Module::Build in inc/',
'requires' => { 'requires' => {
'ExtUtils::Installed' => '1.999',
'ExtUtils::Install' => '1.54', 'ExtUtils::Install' => '1.54',
'ExtUtils::Installed' => '1.999',
'inc::latest' => '0.5' 'inc::latest' => '0.5'
} }
}, },
'PPM_support' => { 'license_creation' => {
'description' => 'Generate PPM files for distributions' 'description' => 'Create licenses automatically in distributions',
} 'requires' => {
'Software::License' => '0.103009'
}
},
'manpage_support' => {
'description' => 'Create Unix man pages',
'requires' => {
'Pod::Man' => 0
}
}
} }
]; ];
$x; } $x; }
\ No newline at end of file
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
http://xml.org/sax/features/namespaces = 1 http://xml.org/sax/features/namespaces = 1
[XML::SAX::Expat] [XML::SAX::Expat]
http://xml.org/sax/features/namespaces = 1
http://xml.org/sax/features/external-general-entities = 1 http://xml.org/sax/features/external-general-entities = 1
http://xml.org/sax/features/namespaces = 1
http://xml.org/sax/features/external-parameter-entities = 1 http://xml.org/sax/features/external-parameter-entities = 1
...@@ -245,7 +245,7 @@ sub import { ...@@ -245,7 +245,7 @@ sub import {
${^WARNING_BITS} ^= ${^WARNING_BITS} ^ ""; ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ "";
# use strict, use utf8; use feature; # use strict, use utf8; use feature;
$^H |= 0x1c820ec0; $^H |= 0x1c820ec0;
@^H{qw(feature_evalbytes feature_say feature_state feature_fc feature___SUB__ feature_unicode feature_switch)} = (1) x 7; @^H{qw(feature_say feature_evalbytes feature_state feature___SUB__ feature_fc feature_unicode feature_switch)} = (1) x 7;
} }
1; 1;
......
#===============================================================================
#
# lib/Filter/Crypto.pm
#
# DESCRIPTION
# Module providing documentation and the version number of the Filter-Crypto
# distribution.
#
# COPYRIGHT
# Copyright (C) 2004-2010, 2012, 2014, 2015 Steve Hay. All rights reserved.
#
# LICENCE
# This module is free software; you can redistribute it and/or modify it under
# the same terms as Perl itself, i.e. under the terms of either the GNU
# General Public License or the Artistic License, as specified in the LICENCE
# file.
#
#===============================================================================
package Filter::Crypto;
use 5.008001;
use strict;
use warnings;
#===============================================================================
# MODULE INITIALIZATION
#===============================================================================
our($VERSION);
BEGIN {
$VERSION = '2.10';
}
1;
__END__
#===============================================================================
# DOCUMENTATION
#===============================================================================
=head1 NAME
Filter::Crypto - Create runnable Perl files encrypted with OpenSSL libcrypto
=head1 SYNOPSIS
# Encrypt a Perl script using the crypt_file script. Run it as usual:
$ crypt_file --in-place hello.pl
$ hello.pl
# Create a PAR archive containing an encrypted Perl script. Run it as usual:
# (This example assumes that you also have PAR installed.)
$ pp -f Crypto -M Filter::Crypto::Decrypt -o hello hello.pl
$ hello
# Display the Filter-Crypto distribution version number:
use Filter::Crypto;
print "This is Filter-Crypto $Filter::Crypto::VERSION\n";
=head1 DESCRIPTION
The Filter-Crypto distribution provides the means to convert your Perl files
into an encrypted, yet still runnable, format to hide the source code from
casual prying eyes.
This is achieved using a Perl source code filter. The encrypted files, produced
using the L<Filter::Crypto::CryptFile|Filter::Crypto::CryptFile> module,
automatically have one (unencrypted) line added to the start of them that loads
the L<Filter::Crypto::Decrypt|Filter::Crypto::Decrypt> module. The latter is a
Perl source code filter that decrypts the remaining (encrypted) part of the Perl
file on the fly when it is run. See L<perlfilter> if you want to know more
about how Perl source code filters work.
These two modules can be built and installed separately, so it is possible to
set-up two separate Perl installations: one containing the
Filter::Crypto::CryptFile module to be used for encrypting your Perl files, and
another containing only the Filter::Crypto::Decrypt module for distributing with
your encrypted Perl files so that they can be run but not easily decrypted.
(Well, not very easily, anyway. Please see the WARNING below.)
Encrypted files can also be produced more conveniently using the B<crypt_file>
script, or (if you also have the L<PAR|PAR> module available) using the
L<PAR::Filter::Crypto|PAR::Filter::Crypto> module. The latter can be utilized
by the standard L<PAR|PAR> tools to produce PAR archives in which your Perl
files are encrypted. The Filter::Crypto::Decrypt module (only) can also be
automatically included in these PAR archives, so this is perhaps the easiest
way to produce redistributable, encrypted Perl files.
The actual encryption and decryption is performed using one of the symmetric
cipher algorithms provided by the OpenSSL libcrypto library. The EVP library
high-level interface functions to the various cipher algorithms themselves are
used so that your choice of algorithm (and also what password or key to use) is
made simply by answering some questions when building this distribution. See
the F<INSTALL> file for more details.
This module itself only contains this documentation and the version number of
the Filter-Crypto distribution as a whole.
=head1 WARNING
Some people regard the whole area of Perl source code encryption as being
morally offensive, given that Perl itself is open source. However, Perl's
Artistic License does specifically allow the distribution of Perl "as part of a
larger (possibly commercial) software distribution," and many people producing
commercial Perl software are uneasy about distributing the source code in easily
accessible form for anyone to see, and want to take more practical action than
involving intellectual property rights lawyers.
That is where software like this comes in, but a word of warning is in order
regarding the security provided by this (and, indeed, any other) source code
decryption filter.
Some of the points below come from a discussion on the perl5-porters mailing
list, in the thread starting here:
L<https://www.nntp.perl.org/group/perl.perl5.porters/2003/10/msg84051.html>;
others are taken from the L<Filter::decrypt|Filter::decrypt> manpage.
In general, it is hopeless to try to prevent everyone from getting at the source
code, especially when it is being run in an environment that you have no control
over, and even more so when the software running it (Perl) is open source
itself.
This technique can I<never> completely hide the original unencrypted source code
from people sufficiently determined to get it. The most it can hope for is to
hide it from casual prying eyes, and to outdo everyone who is using a
precompiled perl (at least from "regular" sources) and everyone who is not
knowledgeable enough to suitably modify the Perl source code before compiling
their own.
Perl source code decryption filters work by intercepting the source stream (read
from the encrypted file) and modifying it (in this case, decrypting it) before
it reaches the Perl parser. Clearly, by the time the source reaches the parser
it must be decrypted, otherwise the script cannot be run. This means that at
some stage every part of the script must be held in memory in an unencrypted
state, so anyone with the appropriate debugging skills will be able to get it.
If perl was built with DEBUGGING then running the script with the perl's B<-Dp>
command-line option makes this much easier. Even without a DEBUGGING perl, the
script can still be run under the Perl debugger (perl's B<-d> command-line
option), whose C<l> command will list the (decrypted) source code that was fed
to the parser.
In fact, with the introduction of the Perl compiler backend modules it is now
easy to get at the decrypted source code without any debugging skills at all.
To quote L<B::Deparse>:
B::Deparse is a backend module for the Perl compiler that generates perl
source code, based on the internal compiled structure that perl itself
creates after parsing a program. The output of B::Deparse won't be exactly
the same as the original source, since perl doesn't keep track of comments
or whitespace, and there isn't a one-to-one correspondence between perl's
syntactical constructions and their compiled form, but it will often be
close.
To make debugging and deparsing more difficult, the source code decryption
filter implemented in this distribution contains checks to try to disallow the
following:
=over 4
=item *
Running under a perl that was built with DEBUGGING (C<-DDEBUGGING>);
=item *
Running under a perl with DEBUGGING flags enabled (B<-D> or $^D);
=item *
Running under the Perl debugger (B<-d>);
=item *
Running under the Perl compiler backend (B<-MO=Deparse>).
=back
You should also not use a perl that was built with C debugging support enabled
(e.g. B<gcc>'s B<-g> option, or B<cl.exe>'s B</Zi> option) and should strip the
perl executable to remove all symbols (e.g. B<gcc>'s B<-s> option).
None of the above checks are infallible, however, because unless the source code
decryption filter module is statically linked against the perl executable then
users can always replace the perl executable being used to run the script with
their own version, perhaps hacked in such a way as to work around the above
checks, and thus with debugging/deparsing capabilities enabled. Such a hacked
version of the perl executable can certainly be produced since Perl is open
source itself.
In fact, it is not difficult for suitably experienced hackers to produce a
modified perl executable that makes it absolutely trivial for them to retrieve
the I<original> unencrypted source code with comments, whitespace and all (i.e.
not just a deparsed reconstruction of it). One example that was mentioned in
the perl5-porters thread cited above is to modify the perl executable to simply
print each line of the decrypted source stream that is fed to the parser, rather
than parsing and running it!
A typical hacker's opinion of all this is perhaps the following delightful
message that I received off-list during that perl5-porters thread from someone
who shall remain anonymous:
"If you don't want anybody to see your source code, why don't you
STICK IT UP YOUR ASS?!"
-- Klortho
=head1 COMPATIBILITY
Before version 2.00 of this distribution, encrypted source code was simply the
raw output of the chosen encryption algorithm, which is typically "binary" data
and therefore susceptible to breakage caused by perl reading source files in
"text" mode, which has become the default on Windows since Perl 5.13.11
(specifically, Perl core commit #270ca148cf).
As of version 2.00 of this distribution, each byte of encrypted source code is
now output as a pair of hexadecimal digits and therefore no longer susceptible
to such breakage.
B<THIS IS AN INCOMPATIBLE CHANGE. CURRENT VERSIONS OF THESE MODULES WILL NOT BE
ABLE TO DECRYPT FILES ENCRYPTED WITH VERSIONS OF THESE MODULES PRIOR TO VERSION
2.00 OF THIS DISTRIBUTION, EVEN WHEN BUILT WITH THE SAME CONFIGURATION OPTIONS.
EXISTING ENCRYPTED FILES WILL NEED TO BE RE-ENCRYPTED.>
=head1 KNOWN BUGS
See L<Filter::Crypto::Decrypt/"KNOWN BUGS">.
=head1 FEEDBACK
Patches, bug reports, suggestions or any other feedback is welcome.
Patches can be sent as GitHub pull requests at
L<https://github.com/steve-m-hay/Filter-Crypto/pulls>.
Bug reports and suggestions can be made on the CPAN Request Tracker at
L<https://rt.cpan.org/Public/Bug/Report.html?Queue=Filter-Crypto>.
Currently active requests on the CPAN Request Tracker can be viewed at
L<https://rt.cpan.org/Public/Dist/Display.html?Status=Active;Queue=Filter-Crypto>.
Please test this distribution. See CPAN Testers Reports at
L<https://www.cpantesters.org/> for details of how to get involved.
Previous test results on CPAN Testers Reports can be viewed at
L<https://www.cpantesters.org/distro/F/Filter-Crypto.html>.
Please rate this distribution on CPAN Ratings at
L<https://cpanratings.perl.org/rate/?distribution=Filter-Crypto>.
=head1 SEE ALSO
B<crypt_file>;
L<Filter::Crypto::CryptFile>,
L<Filter::Crypto::Decrypt>,
L<PAR::Filter::Crypto>;
L<perlfilter>;
L<Filter::decrypt>;
L<PAR>;
L<PAR::Filter>.
In particular, the Filter::decrypt module (part of the "Filter" distribution)
contains a template for a Perl source code decryption filter on which the
Filter::Crypto::Decrypt module itself was based.
=head1 AVAILABILITY
The latest version of this module is available from CPAN (see
L<perlmodlib/"CPAN"> for details) at
L<https://metacpan.org/release/Filter-Crypto> or
L<https://www.cpan.org/authors/id/S/SH/SHAY/> or
L<https://www.cpan.org/modules/by-module/Filter/>.
The latest source code is available from GitHub at
L<https://github.com/steve-m-hay/Filter-Crypto>.
=head1 INSTALLATION
See the F<INSTALL> file.
=head1 AUTHOR
Steve Hay E<lt>L<shay@cpan.org|mailto:shay@cpan.org>E<gt>.
=head1 COPYRIGHT
Copyright (C) 2004-2010, 2012-2015, 2017, 2020, 2021 Steve Hay. All rights
reserved.
=head1 LICENCE
This module is free software; you can redistribute it and/or modify it under the
same terms as Perl itself, i.e. under the terms of either the GNU General Public
License or the Artistic License, as specified in the F<LICENCE> file.
=head1 VERSION
Version 2.10
=head1 DATE
TODO
=head1 HISTORY
See the F<Changes> file.
=cut
#===============================================================================
#===============================================================================
#
# CryptFile/lib/Filter/Crypto/CryptFile.pm
#
# DESCRIPTION
# Module providing the means to convert files to/from an encrypted state in
# which they can be run via Filter::Crypto::Decrypt.
#
# COPYRIGHT
# Copyright (C) 2004-2009, 2012-2014 Steve Hay. All rights reserved.
#
# LICENCE
# This module is free software; you can redistribute it and/or modify it under
# the same terms as Perl itself, i.e. under the terms of either the GNU
# General Public License or the Artistic License, as specified in the LICENCE
# file.
#
#===============================================================================
package Filter::Crypto::CryptFile;
use 5.008001;
use strict;
use warnings;
use Carp qw(carp croak);
use Exporter qw();
use Fcntl qw(:DEFAULT :flock);
use Scalar::Util qw(reftype);
use XSLoader qw();
## no critic (Subroutines::ProhibitSubroutinePrototypes)
sub crypt_file($;$$);
sub _isa_cryptmode($);
sub _isa_filehandle($);
sub _isa_filename($);
#===============================================================================
# MODULE INITIALIZATION
#===============================================================================
our(@ISA, @EXPORT, @EXPORT_OK, $VERSION);
BEGIN {
@ISA = qw(Exporter);
@EXPORT = qw(
CRYPT_MODE_AUTO
CRYPT_MODE_ENCRYPT
CRYPT_MODE_DECRYPT
CRYPT_MODE_ENCRYPTED
CRYPT_MODE_DECRYPTED
crypt_file
);
@EXPORT_OK = qw(
$ErrStr
);
$VERSION = '2.10';
XSLoader::load(__PACKAGE__, $VERSION);
}
# Last error message.
our $ErrStr = '';
#===============================================================================
# PUBLIC API
#===============================================================================
# Autoload the CRYPT_MODE_* flags from the constant() XS function.
sub AUTOLOAD {
our $AUTOLOAD;
# Get the name of the constant to generate a subroutine for.
(my $constant = $AUTOLOAD) =~ s/^.*:://o;
# Avoid deep recursion on AUTOLOAD() if constant() is not defined.
croak('Unexpected error in AUTOLOAD(): constant() is not defined')
if $constant eq 'constant';
my($error, $value) = constant($constant);
# Handle any error from looking up the constant.
croak($error) if $error;
# Generate an in-line subroutine returning the required value.
{
no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitNoStrict)
*$AUTOLOAD = sub { return $value };
}
# Switch to the subroutine that we have just generated.
goto &$AUTOLOAD;
}
sub crypt_file($;$$) {
$ErrStr = '';
my $num_bytes = 0;
if ( @_ == 1 or
(@_ == 2 and (not defined $_[1] or $_[1] eq '' or
_isa_cryptmode($_[1]) )))
{
my($fh, $file, $opened, $flocked);
if (_isa_filehandle($_[0])) {
$fh = $_[0];
$opened = 0;
}
elsif (_isa_filename($_[0])) {
$file = $_[0];
unless (sysopen $fh, $file, O_RDWR | O_BINARY) {
$ErrStr = "Can't open file '$file' for updating: $!";
return;
}
$opened = 1;
}
else {
croak("'$_[0]' is not a filehandle or a file name");
}
if (-f $fh) {
unless (flock $fh, LOCK_EX | LOCK_NB) {
$ErrStr = "Can't acquire exclusive lock on update " .
"filehandle: $!";
local($!, $^E);
close $fh if $opened;
return;
}
$flocked = 1;
}
my $crypt_mode = (@_ == 2 and defined $_[1] and $_[1] ne '')
? $_[1] : CRYPT_MODE_AUTO();
unless (_crypt_fh($fh, $crypt_mode, $num_bytes)) {
local($!, $^E);
$opened ? close $fh : $flocked ? flock $fh, LOCK_UN : 1;
return;
}
if ($opened) {
close $fh or
carp("Can't close file '$file' after updating: $!");
}
elsif ($flocked) {
flock $fh, LOCK_UN or
carp("Can't release lock on filehandle after updating: $!");
}
}
else {
my($in_fh, $in_file, $in_opened, $in_flocked);
if (_isa_filehandle($_[0])) {
$in_fh = $_[0];
$in_opened = 0;
}
elsif (_isa_filename($_[0])) {
$in_file = $_[0];
unless (sysopen $in_fh, $in_file, O_RDONLY | O_BINARY) {
$ErrStr = "Can't open input file '$in_file' for reading: $!";
return;
}
$in_opened = 1;
}
else {
croak("'$_[0]' is not a filehandle or a file name");
}
if (-f $in_fh) {
unless (flock $in_fh, LOCK_SH | LOCK_NB) {
$ErrStr = "Can't acquire shared lock on input filehandle: $!";
local($!, $^E);
close $in_fh if $in_opened;
return;
}
$in_flocked = 1;
}
my($out_fh, $out_file, $out_opened, $out_flocked);
if (_isa_filehandle($_[1])) {
$out_fh = $_[1];
$out_opened = 0;
}
elsif (_isa_filename($_[1])) {
$out_file = $_[1];
unless (sysopen $out_fh, $out_file,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY)
{
$ErrStr = "Can't open output file '$out_file' for writing: $!";
local($!, $^E);
$in_opened ? close $in_fh
: $in_flocked ? flock $in_fh, LOCK_UN : 1;
return;
}
$out_opened = 1;
}
else {
local($!, $^E);
$in_opened ? close $in_fh : $in_flocked ? flock $in_fh, LOCK_UN : 1;
croak("'$_[1]' is not a valid crypt mode or a filehandle or a " .
"file name");
}
if (-f $out_fh) {
unless (flock $out_fh, LOCK_EX | LOCK_NB) {
$ErrStr = "Can't acquire exclusive lock on output " .
"filehandle: $!";
local($!, $^E);
$in_opened ? close $in_fh
: $in_flocked ? flock $in_fh, LOCK_UN : 1;
close $out_fh if $out_opened;
return;
}
$out_flocked = 1;
}
my $crypt_mode;
if (@_ == 3 and defined $_[2] and $_[2] ne '') {
if (_isa_cryptmode($_[2])) {
$crypt_mode = $_[2];
}
else {
local($!, $^E);
$in_opened ? close $in_fh
: $in_flocked ? flock $in_fh, LOCK_UN : 1;
$out_opened ? close $out_fh
: $out_flocked ? flock $out_fh, LOCK_UN : 1;
croak("'$_[2]' is not a valid crypt mode");
}
}
else {
$crypt_mode = CRYPT_MODE_AUTO();
}
unless (_crypt_fhs($in_fh, $out_fh, $crypt_mode, $num_bytes)) {
local($!, $^E);
$in_opened ? close $in_fh
: $in_flocked ? flock $in_fh, LOCK_UN : 1;
$out_opened ? close $out_fh
: $out_flocked ? flock $out_fh, LOCK_UN : 1;
return;
}
if ($in_opened) {
close $in_fh or
carp("Can't close input file '$in_file' after reading: $!");
}
elsif ($in_flocked) {
flock $in_fh, LOCK_UN or
carp("Can't release lock on input filehandle after " .
"reading: $!");
}
if ($out_opened) {
close $out_fh or
carp("Can't close output file '$out_file' after writing: $!");
}
elsif ($out_flocked) {
flock $out_fh, LOCK_UN or
carp("Can't release lock on output filehandle after " .
"writing: $!");
}
}
return $num_bytes ? $num_bytes : '0E0';
}
#===============================================================================
# PRIVATE API
#===============================================================================
sub _isa_cryptmode($) {
my $mode = shift;
return(($mode eq CRYPT_MODE_AUTO() or
$mode eq CRYPT_MODE_ENCRYPT() or
$mode eq CRYPT_MODE_DECRYPT() or
$mode eq CRYPT_MODE_ENCRYPTED() or
$mode eq CRYPT_MODE_DECRYPTED() ));
}
sub _isa_filehandle($) {
my $fh = shift;
return((( ref $fh and reftype($fh) eq 'GLOB') or
(not ref $fh and reftype(\$fh) eq 'GLOB') ) and
defined fileno $fh);
}
sub _isa_filename($) {
my $name = shift;
return(not ref $name and reftype(\$name) eq 'SCALAR');
}
1;
__END__
#===============================================================================
# DOCUMENTATION
#===============================================================================
=head1 NAME
Filter::Crypto::CryptFile - Encrypt (and decrypt) Perl files
=head1 SYNOPSIS
use Filter::Crypto::CryptFile qw(:DEFAULT $ErrStr);
# Encrypt one filehandle (or file name) to another.
crypt_file($in_fh, $out_fh, $crypt_mode) or
die "crypt_file() failed: $ErrStr\n";
crypt_file($in_file, $out_file, $crypt_mode) or
die "crypt_file() failed: $ErrStr\n";
# The crypt mode can be determined automatically.
crypt_file($in_fh, $out_fh) or die "crypt_file() failed: $ErrStr\n";
crypt_file($in_file, $out_file) or die "crypt_file() failed: $ErrStr\n";
# Encrypt one filehandle (or file name) in-place (in memory).
crypt_file($in_out_fh, $crypt_mode) or
die "crypt_file() failed: $ErrStr\n";
crypt_file($in_out_file, $crypt_mode) or
die "crypt_file() failed: $ErrStr\n";
# The crypt mode can be determined automatically.
crypt_file($in_out_fh) or die "crypt_file() failed: $ErrStr\n";
crypt_file($in_out_file) or die "crypt_file() failed: $ErrStr\n";
=head1 DESCRIPTION
This module provides a single function called C<crypt_file()> for converting
files to/from an encrypted state in which they can be run via
L<Filter::Crypto::Decrypt|Filter::Crypto::Decrypt>.
The function takes either a pair of open filehandles (one to read from and one
to write to) or else a single open filehandle (to process "in-place"). (File
names can also be specified instead of open filehandles.) It reads data from
the input source, either encrypts it or decrypts it according to the "crypt
mode", and then writes the result to the output source.
In each case, the "crypt mode" may either be explicitly specified using the
C<CRYPT_MODE_*> flags, or else it can be omitted (or specified as C<undef> or
the null string) in order to be determined automatically by C<crypt_file()>.
=head2 Functions
=over 4
=item C<crypt_file($in_fh, $out_fh[, $crypt_mode])>
=item C<crypt_file($in_out_fh[, $crypt_mode])>
If two open filehandles, $in_fh and $out_fh, are supplied then input is read
from $in_fh, encrypted or decrypted, and the output is written to $out_fh.
Clearly $in_fh must have been opened for reading and $out_fh must have been
opened for writing. Only a small amount of data is held in memory at any time,
so this method is safe to use for "large" files without using unduly large
amounts of memory.
If only one open filehandle, $in_out_fh, is supplied then input is read from it,
encrypted or decrypted, and the output is written back to it after truncating
the file to zero size. In this case, $in_out_fh must have been opened for
"updating" (both reading and writing). Using this method the whole file is read
into memory in one go, so it is not suitable for use on "large" files. This is
unlikely to be a problem in practice, however, since Perl source code files are
rarely, if ever, sufficiently large to cause any trouble in this regard.
Note that the filehandle being written to when encrypting and the filehandle
being read from when decrypting I<must> be opened in "binary" mode on those
platforms where it makes a difference (notably Win32), otherwise the encrypted
"binary" data being written or read may become corrupted by CR-LF translations.
It will also be necessary to open the other filehandle (which the Perl source
code itself is being read from or written to) in "binary" mode too if the Perl
source code happens to contain any "binary" data, e.g. in a C<__DATA__> section.
File names may be supplied instead of open filehandles, in which case they will
be opened appropriately by C<crypt_file()> itself and closed again after use.
(C<crypt_file()> always opens the filehandles in "binary" mode so any "binary"
data in the Perl source code will be correctly handled.)
The optional L<$crypt_mode|"Crypt Mode Flags"> argument specifies whether to
perform encryption or decryption. If it is omitted or specified as C<undef> or
the null string then the crypt mode will be determined automatically by reading
the beginning of the input data. If the beginning is
use Filter::Crypto::Decrypt;
then the data is presumed to be in an encrypted state already so the mode will
be set to C<CRYPT_MODE_DECRYPT>; otherwise the mode will be set to
C<CRYPT_MODE_ENCRYPT>.
On success, returns the number of bytes written (which could be zero if the
input was already in the requested state, in which case the special "zero but
true" value will be returned); on failure returns the undefined value (in scalar
context) or the empty list (in list context) and sets $ErrStr.
=back
=head2 Crypt Mode Flags
The $crypt_mode argument in C<crypt_file()> specifies whether to encrypt or
decrypt the input data, as follows:
=over 4
=item C<CRYPT_MODE_AUTO>
Have the crypt mode determined automatically by the same means as described
under C<crypt_file()> in the case where the $crypt_mode argument is omitted or
specified as C<undef> or the null string.
=item C<CRYPT_MODE_ENCRYPT>
Encrypt the input data and prepend the statement
use Filter::Crypto::Decrypt;
to the output data so that it can be run via
L<Filter::Crypto::Decrypt|Filter::Crypto::Decrypt>. Produces a warning if the
input data already has that statement at the beginning.
=item C<CRYPT_MODE_DECRYPT>
Decrypt the input data after first removing the statement
use Filter::Crypto::Decrypt;
from the beginning. Produces a warning if the input data does not have that
statement at the beginning.
=item C<CRYPT_MODE_ENCRYPTED>
The same as C<CRYPT_MODE_ENCRYPT> except that the encryption is not performed if
the input data already begins with the statement
use Filter::Crypto::Decrypt;
Thus, unencrypted data will be encrypted, while encrypted data will not be
encrypted a second time.
=item C<CRYPT_MODE_DECRYPTED>
The same as C<CRYPT_MODE_DECRYPT> except that the decryption is not attempted if
the input data does not begin with the statement
use Filter::Crypto::Decrypt;
Thus, encrypted data will be decrypted, while unencrypted data will not be
decrypted a second time.
=back
=head2 Variables
=over 4
=item $ErrStr
Last error message.
If the C<crypt_file()> function fails then a description of the last error will
be set in this variable for use in reporting the cause of the failure, much like
the use of the Perl Special Variables C<$!> and C<$^E> after failed system calls
and OS API calls. See L<"Error Values"> for a listing of the possible values of
$ErrStr.
If the function succeeds then this variable will generally be set to the null
string. The only exceptions to this are when the crypt mode was specified as
either C<CRYPT_MODE_ENCRYPTED> or C<CRYPT_MODE_DECRYPTED> and the input data was
found to be already encrypted or decrypted respectively so that no action was
required: in these cases a message to this effect will be set in $ErrStr.
=back
=head1 DIAGNOSTICS
=head2 Warnings and Error Messages
This module may produce the following diagnostic messages. They are classified
as follows (a la L<perldiag>):
(W) A warning (optional).
(F) A fatal error (trappable).
(I) An internal error that you should never see (trappable).
=over 4
=item Can't close file '%s' after updating: %s
(W) The specified file opened by C<crypt_file()> for reading data from and
writing data to when updating a file "in-place" could not be closed after use.
The system error message corresponding to the standard C library C<errno>
variable is also given.
=item Can't close input file '%s' after reading: %s
(W) The specified input file opened by C<crypt_file()> for reading data from
could not be closed after use. The system error message corresponding to the
standard C library C<errno> variable is also given.
=item Can't close output file '%s' after writing: %s
(W) The specified output file opened by C<crypt_file()> for writing data to
could not be closed after use. The system error message corresponding to the
standard C library C<errno> variable is also given.
=item Can't release lock on filehandle after updating: %s
(W) The exclusive lock acquired by C<crypt_file()> on the filehandle used for
reading data from and writing data to when updating a file "in-place" could not
be released after use. The system error message corresponding to the standard
library C<errno> variable is also given.
=item Can't release lock on input filehandle after reading: %s
(W) The shared lock acquired by C<crypt_file()> on the input filehandle used for
reading data from could not be released after use. The system error message
corresponding to the standard C library C<errno> variable is also given.
=item Can't release lock on output filehandle after writing: %s
(W) The exclusive lock acquired by C<crypt_file()> on the output filehandle used
for writing data to could not be released after use. The system error message
corresponding to the standard C library C<errno> variable is also given.
=item chsize/ftruncate not implemented
(F) The attempt by C<crypt_file()> to truncate the file to zero size before
writing the data to it when updating a file "in-place" failed because the
C<chsize()> and C<ftruncate()> functions are not implemented on this system.
=item Input data already contains decryption filter
(W) The crypt mode was specified as C<CRYPT_MODE_ENCRYPT> but data read from the
input filehandle already begins with the statement
use Filter::Crypto::Decrypt;
Perhaps you are attempting to encrypt data when you meant to be decrypting it?
=item Input data does not contain decryption filter
(W) The crypt mode was specified as C<CRYPT_MODE_DECRYPT> but data read from the
input filehandle did not begin with the statement
use Filter::Crypto::Decrypt;
Perhaps you are attempting to decrypt data when you meant to be encrypting it?
=item %s is not a filehandle or a file name
(F) The first parameter for C<crypt_file()> must be either a valid (open)
filehandle or a file name, but the argument passed was neither of these things.
=item %s is not a valid crypt mode
(F) The third parameter for C<crypt_file()> must be either C<undef> or the null
string (meaning determine the crypt mode automatically), or a valid crypt mode
(i.e. one of the C<CRYPT_MODE_*> flags), but the argument passed was neither of
these things.
=item %s is not a valid crypt mode or a filehandle or a file name
(F) The second parameter for C<crypt_file()> must be one of: C<undef> or the
null string (meaning determine the crypt mode automatically), a valid crypt mode
(i.e. one of the C<CRYPT_MODE_*> flags), or a valid (open) filehandle or a file
name, but the argument passed was none of these things.
=item %s is not a valid Filter::Crypto::CryptFile macro
(F) You attempted to lookup the value of the specified constant in the
Filter::Crypto::CryptFile module, but that constant is unknown to this module.
=item No such package '%s'
(F) This module's bootstrap function was called on the specified package, which
does not exist.
=item Random IV may not be cryptographically strong
(W) libcrypto's random number generator failed to generate cryptographically
strong pseudo-random bytes for use as the initialization vector (IV) in the
encryption. A weaker sequence of pseudo-random bytes was used instead, which is
not necessarily unpredictable and may not be suitable for this purpose.
=item Random salt may not be cryptographically strong
(W) libcrypto's random number generator failed to generate cryptographically
strong pseudo-random bytes for use as the salt when performing the key
derivation before encryption. A weaker sequence of pseudo-random bytes was used
instead, which is not necessarily unpredictable and may not be suitable for this
purpose.
=item Unexpected error in AUTOLOAD(): constant() is not defined
(I) There was an unexpected error looking up the value of a constant: the
constant-lookup function itself is apparently not defined.
=item Unexpected return type %d while processing Filter::Crypto::CryptFile macro
%s
(I) There was an unexpected error looking up the value of the specified
constant: the C component of the constant-lookup function returned an unknown
type.
=item Unknown crypt mode '%d'
(I) The XSUB called internally by C<crypt_file()> was passed a crypt mode that
it does not recognize or failed to derive correctly a crypt mode for setting in
the crypto context structure to be used when performing the encryption or
decryption.
=item Unknown crypto context mode '%d'
(I) The crypto context structure used internally when performing encryption or
decryption has been set-up with a crypt mode that it does not recognize.
=item Your vendor has not defined Filter::Crypto::CryptFile macro %s
(I) You attempted to lookup the value of the specified constant in the
Filter::Crypto::CryptFile module, but that constant is apparently not defined.
=back
=head2 Error Values
The C<crypt_file()> function sets $ErrStr to a value indicating the cause of the
error when it fails. The possible values are as follows:
=over 4
=item Can't acquire exclusive lock on output filehandle: %s
The filehandle used by C<crypt_file()> for writing data to could not be locked
for exclusive use. The system error message corresponding to the standard C
library C<errno> variable is also given.
=item Can't acquire exclusive lock on update filehandle: %s
The filehandle used by C<crypt_file()> for reading data from and writing data to
when updating a file "in-place" could not be locked for exclusive use. The
system error message corresponding to the standard C library C<errno> variable
is also given.
=item Can't acquire shared lock on input filehandle: %s
The filehandle used by C<crypt_file()> for reading data from could not be locked
for shared use. The system error message corresponding to the standard C
library C<errno> variable is also given.
=item Can't cleanup cipher context: %s
The cipher context structure used to perform the encryption or decryption could
not be cleaned up after use. The last error message from libcrypto is also
given.
=item Can't decode odd-numbered (%d-byte) length hexadecimal text
The hexadecimal encoding of the encrypted source code, consisting of a pair of
hexadecimal digits for each byte of data, could not be decoded because an odd
number of hexadecimal digits were found.
=item Can't decode non-hexadecimal digit (byte %02x at position %d) in
hexadecimal text
The hexadecimal encoding of the encrypted source code, consisting of a pair of
hexadecimal digits for each byte of data, could not be decoded because a byte
other than a hexadecimal digit was found.
=item Can't derive %d-byte key: %s
libcrypto's PKCS#5 v2.0 compatible key derivation algorithm failed to derive a
key of the specified length from the supplied password for use in the encryption
or decryption. The last error message from libcrypto is also given.
=item Can't finalize cipher context: %s
The cipher context structure used to perform the encryption or decryption could
not be finalized. The last error message from libcrypto is also given.
=item Can't generate %d-byte random salt: %s
libcrypto's random number generator failed to generate the specified number of
pseudo-random bytes for use as the salt when performing the key derivation prior
to encryption. The last error message from libcrypto is also given.
=item Can't generate %d-byte random IV: %s
libcrypto's random number generator failed to generate the specified number of
pseudo-random bytes for use as the initialization vector (IV) in the encryption.
The last error message from libcrypto is also given.
=item Can't initialize cipher context in crypt mode '%d': %s
The cipher context structure used to perform the encryption or decryption could
not be initialized in the specified crypt mode. This is the first stage of the
cipher context structure initialization, performed before setting the key length
and modifying other cipher parameters. The last error message from libcrypto is
also given.
=item Can't initialize cipher context in crypt mode '%d' using %d-byte key: %s
The cipher context structure used to perform the encryption or decryption could
not be initialized in the specified crypt mode with the specified key length.
This is the final stage of the cipher context structure initialization,
performed after setting the key length and modifying other cipher parameters.
The last error message from libcrypto is also given.
=item Can't initialize PRNG
libcrypto's random number generator could not be seeded with enough entropy.
=item Can't open file '%s' for updating: %s
The specified file could not be opened by C<crypt_file()> for reading data from
and writing data to when updating a file "in-place". The system error message
corresponding to the standard C library C<errno> variable is also given.
=item Can't open input file '%s' for reading: %s
The specified file from which to read data could not be opened for reading by
C<crypt_file()>. The system error message corresponding to the standard C
library C<errno> variable is also given.
=item Can't open output file '%s' for writing: %s
The specified file could not be opened by C<crypt_file()> for writing data to.
The system error message corresponding to the standard C library C<errno>
variable is also given.
=item Can't read from input filehandle: %s
There was an error reading data from the input filehandle. The system error
message corresponding to the standard C library C<errno> variable is also given.
=item Can't set key length to %d: %s
The specified key length could not be set for the cipher context structure used
to perform the encryption or decryption. The last error message from libcrypto
is also given.
=item Can't set RC2 effective key bits to %d: %s
The specified effective key bits could not be set for the cipher context
structure used to perform the encryption or decryption when using the RC2
cipher. The last error message from libcrypto is also given.
=item Can't set RC5 number of rounds to %d: %s
The specified number of rounds could not be set for the cipher context structure
used to perform the encryption or decryption when using the RC5 cipher. The
last error message from libcrypto is also given.
=item Can't truncate filehandle: %s
The filehandle used by C<crypt_file()> for reading data from and writing data to
when updating a file "in-place" could not be truncated to zero size before
writing data to it. The system error message corresponding to the standard C
library C<errno> variable is also given.
=item Can't update cipher context with %d bytes of in-text: %s
The cipher context structure used to perform the encryption or decryption could
not be updated with the specified number of bytes of input data. The last error
message from libcrypto is also given.
=item Can't write header line to output filehandle: %s
There was an error writing the statement
use Filter::Crypto::Decrypt;
to the output filehandle. The system error message corresponding to the
standard C library C<errno> variable is also given.
=item Can't write to filehandle: %s
There was an error writing data to the filehandle when updating a file
"in-place". The system error message corresponding to the standard C library
C<errno> variable is also given.
=item Can't write to output filehandle: %s
There was an error writing data to the output filehandle. The system error
message corresponding to the standard C library C<errno> variable is also given.
=item Derived key length is wrong (%d, expected %d)
libcrypto's PKCS#5 v1.5 compatible key derivation algorithm failed to derive a
key of the requested length from the supplied password for use in the encryption
or decryption.
=item Input data was already decrypted
The crypt mode was specified as C<CRYPT_MODE_DECRYPTED> and data read from the
input filehandle does not begin with the statement
use Filter::Crypto::Decrypt;
indicating that the data is probably already decrypted. No action was taken,
and C<crypt_file()> returned success. Use the crypt mode C<CRYPT_MODE_DECRYPT>
if you really want to force decryption in this case.
=item Input data was already encrypted
The crypt mode was specified as C<CRYPT_MODE_ENCRYPTED> and data read from the
input filehandle already begins with the statement
use Filter::Crypto::Decrypt;
indicating that the data is probably already encrypted. No action was taken,
and C<crypt_file()> returned success. Use the crypt mode C<CRYPT_MODE_ENCRYPT>
if you really want to force encryption in this case.
=back
=head1 EXAMPLES
See the B<crypt_file> script for examples of the use of the C<crypt_file()>
function.
=head1 EXPORTS
The following symbols are, or can be, exported by this module:
=over 4
=item Default Exports
C<crypt_file>;
C<CRYPT_MODE_AUTO>,
C<CRYPT_MODE_ENCRYPT>,
C<CRYPT_MODE_DECRYPT>,
C<CRYPT_MODE_ENCRYPTED>,
C<CRYPT_MODE_DECRYPTED>.
=item Optional Exports
C<$ErrStr>.
=item Export Tags
I<None>.
=back
=head1 KNOWN BUGS
I<None>.
=head1 CAVEATS
=over 4
=item *
Note that specifying the "crypt_mode" as C<CRYPT_MODE_AUTO>, C<undef> or the
null string can be used to resolve any ambiguity in the case where
C<crypt_file()> is called with two arguments, namely, did the caller intend
C<crypt_file($in_file, $out_file)> or C<crypt_file($in_out_file, $crypt_mode)>?
In such cases, C<crypt_file()> checks if the second argument is a valid "crypt
mode" before considering if it is a file name, so it normally Does The Right
Thing. However, if you wanted to write the output to a file called F<1> (which
happens to be the value of the C<CRYPT_MODE_ENCRYPT> flag) then calling
crypt_file($in_file, '1');
will not do what you want. In this case, you can call
crypt_file($in_file, '1', CRYPT_MODE_AUTO);
instead to get the desired behaviour (without having to explicitly specify the
crypt mode).
=back
=head1 SEE ALSO
L<Filter::Crypto>.
=head1 ACKNOWLEDGEMENTS
The C<FilterCrypto_PRNGInit()> and C<FilterCrypto_GetRandNum()> functions used
by the XS code are based on code taken from the C<ssl_rand_seed()> and
C<ssl_rand_choosenum()> functions in Apache httpd (version 2.4.9).
Thanks to Steve Henson for help with performing PBE and PKCS#5 v2.0 key
derivation with arbitrary ciphers and non-default key lengths using the OpenSSL
libcrypto library.
=head1 AUTHOR
Steve Hay E<lt>L<shay@cpan.org|mailto:shay@cpan.org>E<gt>.
=head1 COPYRIGHT
Copyright (C) 2004-2009, 2012-2014 Steve Hay. All rights reserved.
=head1 LICENCE
This module is free software; you can redistribute it and/or modify it under the
same terms as Perl itself, i.e. under the terms of either the GNU General Public
License or the Artistic License, as specified in the F<LICENCE> file.
=head1 VERSION
Version 2.10
=head1 DATE
TODO
=head1 HISTORY
See the F<Changes> file.
=cut
#===============================================================================
#===============================================================================
#
# Decrypt/lib/Filter/Crypto/Decrypt.pm
#
# DESCRIPTION
# Module providing a Perl source code filter for running Perl files that have
# been encrypted via Filter::Crypto::CryptFile.
#
# COPYRIGHT
# Copyright (C) 2004-2009, 2012, 2014 Steve Hay. All rights reserved.
#
# LICENCE
# This module is free software; you can redistribute it and/or modify it under
# the same terms as Perl itself, i.e. under the terms of either the GNU
# General Public License or the Artistic License, as specified in the LICENCE
# file.
#
#===============================================================================
package Filter::Crypto::Decrypt;
use 5.008001;
use strict;
use warnings;
use XSLoader qw();
#===============================================================================
# MODULE INITIALIZATION
#===============================================================================
our($VERSION);
BEGIN {
$VERSION = '2.10';
XSLoader::load(__PACKAGE__, $VERSION);
}
# Last error message.
our $ErrStr = '';
1;
__END__
#===============================================================================
# DOCUMENTATION
#===============================================================================
=head1 NAME
Filter::Crypto::Decrypt - Perl source code filter to run encrypted Perl files
=head1 SYNOPSIS
use Filter::Crypto::Decrypt;
=head1 DESCRIPTION
This module provides a Perl source code decryption filter for running files that
have been encrypted via the
L<Filter::Crypto::CryptFile|Filter::Crypto::CryptFile> module.
You should rarely, if ever, need to touch this module. The encrypted files
produced by the L<Filter::Crypto::CryptFile|Filter::Crypto::CryptFile> module
will automatically have the "C<use Filter::Crypto::Decrypt;>" statement added to
the start of them, which is all that is required to bring this decryption filter
into play. See L<perlfilter> if you want to know more about how Perl source
code filters work.
=head1 DIAGNOSTICS
=head2 Warnings and Error Messages
This module may produce the following diagnostic messages. They are classified
as follows (a la L<perldiag>):
(W) A warning (optional).
(F) A fatal error (trappable).
(I) An internal error that you should never see (trappable).
=over 4
=item Can't add MAGIC to decryption filter's SV
(F) The SV used by the source code decryption filter to maintain state could not
be assigned MAGIC to have it automatically free up allocated memory when it is
destroyed.
=item Can't complete decryption: %s
(F) There was an error producing the final block of decrypted data. The cipher
context structure used to perform the source code decryption could not be
finalized so the decryption could not be completed. The last error message from
the decryption code is also given.
=item Can't continue decryption: %s
(F) There was an error reading or decrypting a block of data from the encrypted
Perl file. The cipher context structure used to perform the source code
decryption could not be updated so the decryption could not continue. The last
error message from the decryption code is also given.
=item Can't find MAGIC in decryption filter's SV
(F) The MAGIC assigned to the SV used by the source code decryption filter to
maintain state could not be found.
=item Can't run with DEBUGGING flags
(F) The encrypted Perl file is being run by a perl with DEBUGGING flags enabled,
e.g. C<perl -Dp F<file>>. This is not allowed since it may assist in retrieving
the original unencrypted source code.
=item Can't run with DEBUGGING perl
(F) The encrypted Perl file is being run by a perl that was built with DEBUGGING
enabled, i.e. C<-DDEBUGGING>. This is not allowed since it may assist in
retrieving the original unencrypted source code.
=item Can't run with extra filters
(F) The encrypted Perl file is being run through extra source code filters (i.e.
over and above the decryption filter provided by this module). This is not
allowed since it may assist in retrieving the original unencrypted source code.
=item Can't run with Perl compiler backend
(F) The encrypted Perl file is being run by a perl with the Perl compiler
backend enabled, e.g. C<perl -MO=Deparse F<file>>. This is not allowed since it
may assist in retrieving the original unencrypted source code.
=item Can't run with Perl debugger
(F) The encrypted Perl file is being run by a perl with the Perl debugger
enabled, e.g. C<perl -d:ptkdb F<file>>. This is not allowed since it may assist
in retrieving the original unencrypted source code.
=item Can't start decryption: %s
(F) The cipher context structure used to perform the source code decryption
could not be initialized so the decryption could not be started. The last error
message from the decryption code is also given.
=item Found wrong MAGIC in decryption filter's SV: No valid mg_ptr
(F) The MAGIC found in the SV used by the source code decryption filter to
maintain state was not the correct MAGIC since it did not contain a valid
C<mg_ptr> member.
=item Found wrong MAGIC in decryption filter's SV: Wrong mg_ptr "signature"
(F) The MAGIC found in the SV used by the source code decryption filter to
maintain state was not the correct MAGIC since it did not contain the correct
"signature" in its C<mg_ptr> member.
=item No such package '%s'
(F) This module's bootstrap function was called on the specified package, which
does not exist.
=item Unknown crypto context mode '%d'
(I) The crypto context structure used internally when performing decryption has
been set-up with a crypt mode that it does not recognize.
=back
=head1 EXPORTS
I<None>.
=head1 KNOWN BUGS
=over
=item C<__DATA__> is not accessible when running encrypted files.
See L<https://rt.cpan.org/Ticket/Display.html?id=54370>.
=item Infinite loop when running a program using an encrypted Data::Alias.
See L<https://rt.cpan.org/Ticket/Display.html?id=122951>.
=back
=head1 SEE ALSO
L<Filter::Crypto>;
L<Filter::CBC>, L<Crypt::License>.
The latter two modules (in separate CPAN distributions, not related to the
Filter-Crypto distribution in any way) are both Perl-level source code filters
and are thus even less secure than this module is. (This module's filter code
is written in XS and C.)
=head1 ACKNOWLEDGEMENTS
Much of the XS code is based on that in the Filter::decrypt module (version
1.49), written by Paul Marquess.
Thanks to Nick Ing-Simmons for help in getting the MAGIC attached to the
decryption filter's SV working.
=head1 AUTHOR
Steve Hay E<lt>L<shay@cpan.org|mailto:shay@cpan.org>E<gt>.
=head1 COPYRIGHT
Copyright (C) 2004-2009, 2012-2014 Steve Hay. All rights reserved.
=head1 LICENCE
This module is free software; you can redistribute it and/or modify it under the
same terms as Perl itself, i.e. under the terms of either the GNU General Public
License or the Artistic License, as specified in the F<LICENCE> file.
=head1 VERSION
Version 2.10
=head1 DATE
TODO
=head1 HISTORY
See the F<Changes> file.
=cut
#===============================================================================
package Imager::File::PNG;
use 5.006;
use strict;
use Imager;
BEGIN {
our $VERSION = "0.99";
require XSLoader;
XSLoader::load('Imager::File::PNG', $VERSION);
}
sub read {
my ($class, $im, $io, %hsh) = @_;
my $flags = 0;
$hsh{png_ignore_benign_errors}
and $flags |= IMPNG_READ_IGNORE_BENIGN_ERRORS;
$im->{IMG} = i_readpng_wiol($io, $flags);
unless ($im->{IMG}) {
$im->_set_error(Imager->_error_as_msg);
return;
}
return $im;
}
Imager->register_reader
(
type=>'png',
single =>
sub {
my ($im, $io, %hsh) = @_;
__PACKAGE__->read($im, $io, %hsh);
},
);
sub write {
my ($class, $im, $io, %hsh) = @_;
$im->_set_opts(\%hsh, "i_", $im);
$im->_set_opts(\%hsh, "png_", $im);
unless (i_writepng_wiol($im->{IMG}, $io)) {
$im->_set_error(Imager->_error_as_msg);
return;
}
return $im;
}
Imager->register_writer
(
type=>'png',
single =>
sub {
my ($im, $io, %hsh) = @_;
return __PACKAGE__->write($im, $io, %hsh);
},
);
__END__
=head1 NAME
Imager::File::PNG - read and write PNG files
=head1 SYNOPSIS
use Imager;
my $img = Imager->new;
$img->read(file=>"foo.png")
or die $img->errstr;
$img->write(file => "foo.png")
or die $img->errstr;
=head1 DESCRIPTION
Imager's PNG support is documented in L<Imager::Files>.
=head1 METHODS
Two low level class methods are provided, most for use by
L<Imager::File::APNG>, but it may later be used for other formats that
can encapsulate PNG such as ICO.
=over
=item C<< Imager::File::PNG->read($im, $io, %hsh) >>
Read a PNG image from the supplied L<Imager::IO> object C<$io> into
the L<Imager> object C<$im>.
Returns a true value on success.
=item C<< Imager::File::PNG->write($im, $io, %hsh) >>
Write a PNG image to the supplied L<Imager::IO> object C<$io> from the
L<Imager> object C<$im>.
Returns a true value on success.
=back
=head1 AUTHOR
Tony Cook <tonyc@cpan.org>
=head1 SEE ALSO
L<Imager>, L<Imager::Files>.
=cut
#===============================================================================
#
# lib/PAR/Filter/Crypto.pm
#
# DESCRIPTION
# PAR::Filter sub-class providing the means to convert files to an encrypted
# state in which they can be run via Filter::Crypto::Decrypt, primarily for
# use in creating PAR archives in which the Perl files are encrypted.
#
# COPYRIGHT
# Copyright (C) 2004-2008, 2012, 2014 Steve Hay. All rights reserved.
#
# LICENCE
# This module is free software; you can redistribute it and/or modify it under
# the same terms as Perl itself, i.e. under the terms of either the GNU
# General Public License or the Artistic License, as specified in the LICENCE
# file.
#
#===============================================================================
package PAR::Filter::Crypto;
use 5.008001;
use strict;
use warnings;
use Carp qw(carp croak);
use Fcntl qw(:seek);
use File::Temp qw(tempfile);
use Filter::Crypto::CryptFile qw(:DEFAULT $ErrStr);
use PAR::Filter qw();
#===============================================================================
# CLASS INITIALIZATION
#===============================================================================
our(@ISA, $VERSION);
BEGIN {
@ISA = qw(PAR::Filter);
$VERSION = '2.10';
}
#===============================================================================
# PUBLIC API
#===============================================================================
# This method is based on the apply() method in the PAR::Filter::Bytecode module
# in the PAR::Packer distribution (version 1.017).
sub apply {
my($class, $ref, $filename, $name) = @_;
# If we're encrypting modules (e.g. pp -F Crypto ...) then be careful not to
# encrypt the decryption module.
return 1 if $filename eq 'Filter/Crypto/Decrypt.pm';
if (eval { require Module::ScanDeps } and
$Module::ScanDeps::VERSION eq '0.75')
{
carp('Detected Module::ScanDeps version 0.75, which may not work ' .
'correctly with ' . __PACKAGE__);
}
# Open a temporary file. (The temporary file will be deleted automatically
# since tempfile() is called in scalar context.)
my $fh = tempfile();
# Write the source code to be encrypted to the temporary filehandle.
print $fh $$ref;
# Rewind the filehandle so that the encryption knows where to begin.
seek $fh, 0, SEEK_SET or
croak("Can't rewind temporary filehandle before encryption: $!");
# Encrypt the source code.
crypt_file($fh, CRYPT_MODE_ENCRYPT) or
croak("crypt_file() failed: $ErrStr");
# Rewind the filehandle again and read the now-encrypted source code from it
# back into the scalar referred to by $ref.
seek $fh, 0, SEEK_SET or
croak("Can't rewind temporary filehandle after encryption: $!");
{
local $/;
$$ref = <$fh>;
}
close $fh or
carp("Can't close temporary filehandle after encryption: $!");
return 1;
}
1;
__END__
#===============================================================================
# DOCUMENTATION
#===============================================================================
=head1 NAME
PAR::Filter::Crypto - Encrypt Perl files in PAR archives
=head1 SYNOPSIS
# Create a PAR archive containing an encrypted Perl script:
$ pp -f Crypto -M Filter::Crypto::Decrypt -o hello hello.pl
# The same, but with included modules encrypted as well:
$ pp -f Crypto -F Crypto -M Filter::Crypto::Decrypt -o hello hello.pl
# Encrypt Perl source code in $code:
use PAR::Filter::Crypto;
PAR::Filter::Crypto->apply(\$code);
=head1 DESCRIPTION
This module is a L<PAR::Filter|PAR::Filter> sub-class for producing PAR archives
containing encrypted Perl files. The PAR::Filter class itself is part of the
L<PAR|PAR> distribution, and is clearly a prerequisite for using this sub-class.
The usual means of producing a PAR archive is using the B<pp> script, which also
comes with the PAR distribution. That script's B<-f> and B<-F> command-line
options can be used to specify a "filter" through which to pass the Perl files
being put into the PAR archive. Specifying this sub-class as the filter (i.e.
"B<-f Crypto>" for scripts and/or "B<-F Crypto>" for modules) means that the
Perl files will be encrypted using the
L<Filter::Crypto::CryptFile|Filter::Crypto::CryptFile> module. The resulting
encrypted files are what will be placed in the PAR archive.
Note that the encrypted script requires the
L<Filter::Crypto::Decrypt|Filter::Crypto::Decrypt> module in order to decrypt
itself when it is run. The original Perl script will not have specified any
such dependency, so B<pp> will not automatically include that module in the PAR
archive for you. Therefore, you must use the B<-M> option to force that module
to be included. Also note that if you use the B<-F> option to encrypt modules
as well then the filtering will automatically skip the
L<Filter::Crypto::Decrypt|Filter::Crypto::Decrypt> module itself for obvious
reasons. A typical B<pp> invocation is thus something like:
$ pp -f Crypto -F Crypto -M Filter::Crypto::Decrypt -o hello hello.pl
(Version 0.75 of the L<Module::ScanDeps|Module::ScanDeps> module, used by B<pp>
to scan for dependencies that need including in the PAR archive, is known to
have problems finding shared library files for modules specified by B<pp>'s
B<-M> option (as illustrated above). If you find that the shared library file
for Filter::Crypto::Decrypt is missing from your PAR archive then you need to
upgrade Module::ScanDeps to version 0.76 or higher.)
Of course, you must not include the Filter::Crypto::CryptFile module as well,
otherwise people to whom you distribute your PAR archive will have the means to
easily decrypt the encrypted Perl script within it!
Also, note that the script is encrypted by reading its entire contents into
memory, encrypting it in memory, and then writing it out to disk. This should
be safe for most purposes given that Perl scripts are typically not very large,
but other methods should be considered instead if this is likely to cause
out-of-memory errors due to the size of the scripts, e.g. if the scripts have
very large C<__DATA__> sections.
=head2 Methods
=over 4
=item C<apply($ref)>
Class method. Encrypts the Perl source code referred to by $ref, and replaces
the code referred to by $ref with the encrypted code. Thus, the code in $$ref
gets encrypted "in-place".
Returns 1 on success, or C<croak()>s on failure (since the usual caller,
PAR::Filter::apply(), does not bother checking the return value (as of
PAR::Filter version 0.02, at least)).
=back
=head1 DIAGNOSTICS
=head2 Warnings and Error Messages
This module may produce the following diagnostic messages. They are classified
as follows (a la L<perldiag>):
(W) A warning (optional).
(F) A fatal error (trappable).
(I) An internal error that you should never see (trappable).
=over 4
=item Can't close temporary filehandle after encryption: %s
(W) The temporary file used to perform the encryption could not be closed after
use. The system error message corresponding to the standard C library C<errno>
variable is also given.
=item Can't rewind temporary filehandle before encryption: %s
(F) The temporary file used to perform the encryption could not be rewound
before encrypting the source that was just written to it. The system error
message corresponding to the standard C library C<errno> variable is also given.
=item Can't rewind temporary filehandle after encryption: %s
(F) The temporary file used to perform the encryption could not be rewound after
encrypting the source code that was written to it. The system error message
corresponding to the standard C library C<errno> variable is also given.
=item crypt_file() failed: %s
(F) The C<crypt_file()> function from the Filter::Crypto::CryptFile module that
is used to perform the encryption failed. The last error message from the
Filter::Crypto::CryptFile module is also given.
=item Detected Module::ScanDeps version 0.75, which may not work correctly with
PAR::Filter::Crypto
(W) Your current installation of the Module::ScanDeps module, used by B<pp> to
scan for dependencies that need including in the PAR archive, was found to be
version 0.75, which is known to have problems finding shared library files for
modules specified by B<pp>'s B<-M> option. If you are running B<pp> with the
B<-M> option and find that the shared library file for Filter::Crypto::Decrypt
is missing from your PAR archive then you need to upgrade Module::ScanDeps to
version 0.76 or higher.
=back
=head1 EXPORTS
I<None>.
=head1 KNOWN BUGS
I<None>.
=head1 SEE ALSO
L<PAR::Filter>;
L<Filter::Crypto>.
=head1 ACKNOWLEDGEMENTS
The C<apply()> method is based on that in the PAR::Filter::Bytecode module in
the PAR::Packer distribution (version 1.017), written by Audrey Tang.
=head1 AUTHOR
Steve Hay E<lt>L<shay@cpan.org|mailto:shay@cpan.org>E<gt>.
=head1 COPYRIGHT
Copyright (C) 2004-2008, 2012, 2014 Steve Hay. All rights reserved.
=head1 LICENCE
This module is free software; you can redistribute it and/or modify it under the
same terms as Perl itself, i.e. under the terms of either the GNU General Public
License or the Artistic License, as specified in the F<LICENCE> file.
=head1 VERSION
Version 2.10
=head1 DATE
TODO
=head1 HISTORY
See the F<Changes> file.
=cut
#===============================================================================
/opt/thirdlane/perl_lib/local/dist/bin/instmodsh /opt/thirdlane/perl_lib/local/dist/bin/instmodsh
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Command.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Command.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Command/MM.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Command/MM.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Install.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Installed.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Liblist.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Liblist.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Liblist/Kid.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Liblist/Kid.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/MM.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/MM.pm
...@@ -34,5 +32,4 @@ ...@@ -34,5 +32,4 @@
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/MakeMaker/version/vpp.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/MakeMaker/version/vpp.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Mkbootstrap.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Mkbootstrap.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Mksymlists.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Mksymlists.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/Packlist.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/testlib.pm /opt/thirdlane/perl_lib/local/dist/lib/perl5/ExtUtils/testlib.pm
/usr/local/bin/crypt_file
/usr/local/lib64/perl5/Filter/Crypto.pm
/usr/local/lib64/perl5/Filter/Crypto/CryptFile.pm
/usr/local/lib64/perl5/Filter/Crypto/Decrypt.pm
/usr/local/lib64/perl5/PAR/Filter/Crypto.pm
/usr/local/lib64/perl5/auto/Filter/Crypto/CryptFile/CryptFile.so
/usr/local/lib64/perl5/auto/Filter/Crypto/Decrypt/Decrypt.so
/usr/local/share/man/man1/crypt_file.1
/usr/local/share/man/man3/Filter::Crypto.3pm
/usr/local/share/man/man3/Filter::Crypto::CryptFile.3pm
/usr/local/share/man/man3/Filter::Crypto::Decrypt.3pm
/usr/local/share/man/man3/PAR::Filter::Crypto.3pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/x86_64-linux-thread-multi/Imager/File/PNG.pm
/opt/thirdlane/perl_lib/local/dist/lib/perl5/x86_64-linux-thread-multi/auto/Imager/File/PNG/PNG.so
libz.so.1.2.11
\ No newline at end of file
libz.so.1.2.11
\ No newline at end of file
.TH QRENCODE 1 "Sep. 21, 2017" "qrencode 4.0.2"
.SH NAME
qrencode \- Encode input data in a QR Code and save as a PNG or EPS image.
.SH SYNOPSIS
.B "qrencode"
[OPTION]...
[STRING]
.SH DESCRIPTION
Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
symbology that can be scanned by handy terminals such as a mobile phone with
CCD. The capacity of QR Code is up to 7000 digits or 4000 characters, and has
high robustness.
Qrencode is a utility software using libqrencode to encode string data in
a QR Code and save as a PNG or EPS image.
.SH OPTIONS
.TP
.B \-h, \-\-help
display help message.
.TP
.B \-o FILENAME, \-\-output=FILENAME
write image to FILENAME. If '\-' is specified, the result will be output to standard output. If \-S is given, structured symbols are written to FILENAME-01.png, FILENAME-02.png, ... (suffix is removed from FILENAME, if specified)
.TP
.B \-r FILENAME, \-\-read\-from=FILENAME
read input data from FILENAME.
.TP
.B \-s NUMBER, \-\-size=NUMBER
specify the size of dot (pixel). (default=3)
.TP
.B \-l {LMQH}, \-\-level={LMQH}
specify error correction level from L (lowest) to H (highest). (default=L)
.TP
.B \-v NUMBER, \-\-symversion=NUMBER
specify the minimum version of the symbol. See SYMBOL VERSIONS for more information. (default=auto)
.TP
.B \-m NUMBER, \-\-margin=NUMBER
specify the width of margin. (default=4)
.TP
.B \-d NUMBER, \-\-dpi=NUMBER
specify the DPI of the generated PNG. (default=72)
.TP
.PD 0
.B \-t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}
.TP
.PD
.B \-\-type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}
specify the type of the generated image. (default=PNG)
.TP
.B \-S, \-\-structured
make structured symbols. Version must be specified.
.TP
.B \-k, \-\-kanji
assume that the input text contains kanji (shift-jis).
.TP
.B \-c, \-\-casesensitive
encode lower-case alphabet characters in 8-bit mode. (default)
.TP
.B \-i, \-\-ignorecase
ignore case distinctions and use only upper-case characters.
.TP
.B \-8, \-\-8bit
encode entire data in 8-bit mode. \-k, \-c and \-i will be ignored.
.TP
.B \-M, \-\-micro
encode in a Micro QR Code. (experimental)
.TP
.PD 0
.B \-\-foreground=RRGGBB[AA]
.TP
.PD
.B \-\-background=RRGGBB[AA]
specify foreground/background color in hexadecimal notation.
6-digit (RGB) or 8-digit (RGBA) form are supported.
Color output support available only in PNG, EPS and SVG.
.TP
.B \-V, \-\-version
display the version number and copyrights of the qrencode.
.TP
.B \-\-verbose
display verbose information to stderr.
.TP
.B [STRING]
input data. If it is not specified, data will be taken from standard input.
.SH SYMBOL VERSIONS
The symbol versions of QR Code range from Version 1 to Version 40.
Each version has a different module configuration or number of modules,
ranging from Version 1 (21 x 21 modules) up to Version 40 (177 x 177 modules).
Each higher version number comprises 4 additional modules per side by default.
See http://www.qrcode.com/en/about/version.html for a detailed version list.
.SH EXAMPLES
.TP
.B qrencode \-l L \-v 1 \-o output.png 'Hello, world!'
encode into a symbol version 1, level L.
.TP
.B qrencode \-iSv 1 \-\-output=output.png
read standard input and encode it into a structured-appended symbols in
case-insensitive mode.
.TP
.B qrencode \-S \-v 40 \-l L \-r bigfile.txt \-o output.png
read input data from bigfile.txt and encode into a symbol version 40, level L.
.SH AUTHOR
Written by Kentaro Fukuchi.
.SH RESOURCES
.TP
Main Web Site: https://fukuchi.org/works/qrencode/
.TP
Source code repository: https://github.com/fukuchi/libqrencode/
.SH COPYRIGHT
Copyright (C) 2006-2017 Kentaro Fukuchi.
This source diff could not be displayed because it is too large. You can view the blob instead.
.TH LIBPNGPF 3 "April 14, 2019"
.SH NAME
libpng \- Portable Network Graphics (PNG) Reference Library 1.6.37
(private functions)
.SH SYNOPSIS
\fB#include \fI"pngpriv.h"
\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer
\fP\fImaintained\fP\fB, now that the private function prototypes are hidden in
\fP\fIpngpriv.h\fP\fB and not accessible to applications. Look in
\fP\fIpngpriv.h\fP\fB for the prototypes and a short description of each
function.
.SH DESCRIPTION
The functions previously listed here are used privately by libpng and are not
available for use by applications. They are not "exported" to applications
using shared libraries.
.SH "SEE ALSO"
.BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5)
.SH AUTHORS
Cosmin Truta, Glenn Randers-Pehrson
.TH PNG 5 "April 14, 2019"
.SH NAME
png \- Portable Network Graphics (PNG) format
.SH DESCRIPTION
PNG (Portable Network Graphics) is an extensible file format for the
lossless, portable, well-compressed storage of raster images. PNG
provides a patent-free replacement for GIF, and can also replace many
common uses of TIFF. Indexed-color, grayscale, and truecolor images are
supported, plus an optional alpha channel. Sample depths range from
1 to 16 bits.
.br
PNG is designed to work well in online viewing applications, such
as the World Wide Web, so it is fully streamable with a progressive
display option. PNG is robust, providing both full file integrity
checking and fast, simple detection of common transmission errors.
Also, PNG can store gamma and chromaticity data for improved color
matching on heterogeneous platforms.
.SH "SEE ALSO"
.BR "libpng"(3), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5)
.LP
PNG Specification (Second Edition), November 2003:
.IP
.br
https://www.w3.org/TR/2003/REC-PNG-20031110/
.LP
PNG 1.2 Specification, July 1999:
.IP
.br
https://png-mng.sourceforge.io/pub/png/spec/1.2/
.LP
PNG 1.0 Specification, October 1996:
.IP
.br
RFC 2083
.br
https://www.ietf.org/rfc/rfc2083.txt
.IP
.br
or W3C Recommendation
.br
https://www.w3.org/TR/REC-png-961001
.SH AUTHORS
This man page: Cosmin Truta, Glenn Randers-Pehrson
.LP
Portable Network Graphics (PNG) Specification (Second Edition)
Information technology - Computer graphics and image processing -
Portable Network Graphics (PNG): Functional specification.
ISO/IEC 15948:2003 (E) (November 10, 2003): David Duce and others.
.LP
Portable Network Graphics (PNG) Specification Version 1.2 (July 8, 1999):
Glenn Randers-Pehrson and others (png-list).
.LP
Portable Network Graphics (PNG) Specification Version 1.0 (October 1, 1996):
Thomas Boutell and others (png-list).
.SH COPYRIGHT
.LP
This man page is
.br
Copyright (c) 2018-2019 Cosmin Truta.
.br
Copyright (c) 1998-2006 Glenn Randers-Pehrson.
.br
See png.h for conditions of use and distribution.
.LP
The PNG Specification (Second Edition) is
.br
Copyright (c) 2003 W3C. (MIT, ERCIM, Keio), All Rights Reserved.
.LP
The PNG-1.2 Specification is
.br
Copyright (c) 1999 Glenn Randers-Pehrson.
.br
See the specification for conditions of use and distribution.
.LP
The PNG-1.0 Specification is
.br
Copyright (c) 1996 Massachusetts Institute of Technology.
.br
See the specification for conditions of use and distribution.
.\" end of man page
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment