@@ -1,11 +1,19 @@
________________________________________________________________________________
- Filter::Crypto, Version 2.03
+ Filter::Crypto, Version 2.04
________________________________________________________________________________
Revision history for Perl extension Filter::Crypto.
_________________
+v2.04 19 Feb 2014
+
+ - Fixed crypt_file's "-c encrypted" and "-c decrypted" options when used in
+ conjunction with the "-e tempfile" option. These combinations of options
+ previously caused the input file to be replaced with a zero length file.
+ (Fixes [cpan #93152].)
+_________________
+
v2.03 08 Jul 2013
- Improved crypto library detection so that the library is now correctly
@@ -6,7 +6,7 @@
* C and XS portions of Filter::Crypto::CryptFile module.
*
* COPYRIGHT
- * Copyright (C) 2004-2009, 2012 Steve Hay. All rights reserved.
+ * Copyright (C) 2004-2009, 2012, 2014 Steve Hay. All rights reserved.
*
* LICENCE
* You may distribute under the terms of either the GNU General Public License
@@ -90,20 +90,21 @@ typedef enum {
#endif
static bool FilterCrypto_CryptFh(pTHX_ PerlIO *in_fh, PerlIO *out_fh,
- FILTER_CRYPTO_MODE_EX crypt_mode_ex);
+ FILTER_CRYPTO_MODE_EX crypt_mode_ex, SV* num_bytes);
static bool FilterCrypto_OutputData(pTHX_ SV *from_sv, bool encode_mode,
- bool update_mode, PerlIO *to_fh, SV *to_sv);
+ bool update_mode, PerlIO *to_fh, SV *to_sv, SV* num_bytes);
static const char *filter_crypto_use_text = "use Filter::Crypto::Decrypt;\n";
/*
* Function to encrypt or decrypt data from one filehandle to either another
* filehandle or back to itself.
- * Returns a bool to indicate success or failure.
+ * Returns a bool to indicate success or failure and sets *num_bytes to the
+ * number of bytes written.
*/
static bool FilterCrypto_CryptFh(pTHX_ PerlIO *in_fh, PerlIO *out_fh,
- FILTER_CRYPTO_MODE_EX crypt_mode_ex)
+ FILTER_CRYPTO_MODE_EX crypt_mode_ex, SV* num_bytes)
{
bool encode_mode;
bool update_mode = FALSE;
@@ -120,6 +121,9 @@ static bool FilterCrypto_CryptFh(pTHX_ PerlIO *in_fh, PerlIO *out_fh,
unsigned char *in_text = (unsigned char *)SvPVX(in_sv);
const unsigned char *buf_text;
+ SvIOK_only_UV(num_bytes);
+ sv_setuv(num_bytes, 0);
+
SvPOK_only(in_sv);
SvPOK_only(in2_sv);
SvPOK_only(out_sv);
@@ -251,6 +255,8 @@ static bool FilterCrypto_CryptFh(pTHX_ PerlIO *in_fh, PerlIO *out_fh,
#endif
}
+ sv_setuv(num_bytes, SvUV(num_bytes) + use_len);
+
/* Remember that we have input data in in_text that still needs to
* be encrypted and output. */
have_in_text = TRUE;
@@ -315,7 +321,7 @@ static bool FilterCrypto_CryptFh(pTHX_ PerlIO *in_fh, PerlIO *out_fh,
/* Write the output to the temporary output buffer or output
* filehandle as appropriate. */
if (!FilterCrypto_OutputData(aTHX_ out_sv, encode_mode, update_mode,
- out_fh, buf_sv))
+ out_fh, buf_sv, num_bytes))
{
FilterCrypto_CryptoFree(aTHX_ ctx);
ctx = NULL;
@@ -354,7 +360,7 @@ static bool FilterCrypto_CryptFh(pTHX_ PerlIO *in_fh, PerlIO *out_fh,
/* Write the final block of output to the temporary output buffer or output
* filehandle as appropriate. */
if (!FilterCrypto_OutputData(aTHX_ out_sv, encode_mode, update_mode, out_fh,
- buf_sv))
+ buf_sv, num_bytes))
{
FilterCrypto_CryptoFree(aTHX_ ctx);
ctx = NULL;
@@ -399,11 +405,12 @@ static bool FilterCrypto_CryptFh(pTHX_ PerlIO *in_fh, PerlIO *out_fh,
* Function to output data from a given SV to either a filehandle or to another
* SV. The output bytes can be optionally encoded as pairs of hexadecimal
* digits. Zeroes the length of the given SV after output.
- * Returns a bool to indicate success or failure.
+ * Returns a bool to indicate success or failure and adds the number of bytes
+ * written to a third given SV.
*/
static bool FilterCrypto_OutputData(pTHX_ SV *from_sv, bool encode_mode,
- bool update_mode, PerlIO *to_fh, SV *to_sv)
+ bool update_mode, PerlIO *to_fh, SV *to_sv, SV* num_bytes)
{
SV *from2_sv = sv_2mortal(newSV(BUFSIZ * 2));
SvPOK_only(from2_sv);
@@ -425,6 +432,8 @@ static bool FilterCrypto_OutputData(pTHX_ SV *from_sv, bool encode_mode,
"Appended %d bytes to output buffer", SvCUR(from2_sv)
);
#endif
+
+ sv_setuv(num_bytes, SvUV(num_bytes) + SvCUR(from2_sv));
}
else {
/* Get the data and length to output. */
@@ -445,6 +454,8 @@ static bool FilterCrypto_OutputData(pTHX_ SV *from_sv, bool encode_mode,
"Wrote %d bytes to output stream", from2_len
);
#endif
+
+ sv_setuv(num_bytes, SvUV(num_bytes) + from2_len);
}
FilterCrypto_SvSetCUR(from_sv, 0);
@@ -485,16 +496,18 @@ _debug_mode();
# called with one in-out filehandle.
void
-_crypt_fh(fh, crypt_mode_ex);
- PROTOTYPE: $$
+_crypt_fh(fh, crypt_mode_ex, num_bytes);
+ PROTOTYPE: $$$
INPUT:
InOutStream fh;
FILTER_CRYPTO_MODE_EX crypt_mode_ex
+ SV* num_bytes
PPCODE:
{
- if (FilterCrypto_CryptFh(aTHX_ fh, (PerlIO *)NULL, crypt_mode_ex))
+ if (FilterCrypto_CryptFh(aTHX_ fh, (PerlIO *)NULL, crypt_mode_ex,
+ num_bytes))
XSRETURN_YES;
else
XSRETURN_EMPTY;
@@ -504,17 +517,18 @@ _crypt_fh(fh, crypt_mode_ex);
# called with one input filehandle and one output filehandle.
void
-_crypt_fhs(in_fh, out_fh, crypt_mode_ex);
- PROTOTYPE: $$$
+_crypt_fhs(in_fh, out_fh, crypt_mode_ex, num_bytes);
+ PROTOTYPE: $$$$
INPUT:
InputStream in_fh;
OutputStream out_fh;
FILTER_CRYPTO_MODE_EX crypt_mode_ex;
+ SV* num_bytes;
PPCODE:
{
- if (FilterCrypto_CryptFh(aTHX_ in_fh, out_fh, crypt_mode_ex))
+ if (FilterCrypto_CryptFh(aTHX_ in_fh, out_fh, crypt_mode_ex, num_bytes))
XSRETURN_YES;
else
XSRETURN_EMPTY;
@@ -7,7 +7,7 @@
# which they can be run via Filter::Crypto::Decrypt.
#
# COPYRIGHT
-# Copyright (C) 2004-2009, 2012-2013 Steve Hay. All rights reserved.
+# Copyright (C) 2004-2009, 2012-2014 Steve Hay. All rights reserved.
#
# LICENCE
# You may distribute under the terms of either the GNU General Public License
@@ -55,7 +55,7 @@ BEGIN {
$ErrStr
);
- $VERSION = '2.03';
+ $VERSION = '2.04';
XSLoader::load(__PACKAGE__, $VERSION);
}
@@ -96,6 +96,7 @@ sub AUTOLOAD {
sub crypt_file($;$$) {
$ErrStr = '';
+ my $num_bytes = 0;
if ( @_ == 1 or
(@_ == 2 and (not defined $_[1] or $_[1] eq '' or
@@ -132,7 +133,7 @@ sub crypt_file($;$$) {
my $crypt_mode = (@_ == 2 and defined $_[1] and $_[1] ne '')
? $_[1] : CRYPT_MODE_AUTO();
- unless (_crypt_fh($fh, $crypt_mode)) {
+ unless (_crypt_fh($fh, $crypt_mode, $num_bytes)) {
local($!, $^E);
$opened ? close $fh : $flocked ? flock $fh, LOCK_UN : 1;
return;
@@ -231,7 +232,7 @@ sub crypt_file($;$$) {
$crypt_mode = CRYPT_MODE_AUTO();
}
- unless (_crypt_fhs($in_fh, $out_fh, $crypt_mode)) {
+ 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;
@@ -261,7 +262,7 @@ sub crypt_file($;$$) {
}
}
- return 1;
+ return $num_bytes ? $num_bytes : '0E0';
}
#===============================================================================
@@ -391,8 +392,10 @@ 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>.
-Returns 1 on success, or a false value (namely, the undefined value in scalar
-context or the empty list in list context) and sets $ErrStr on failure.
+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
@@ -896,7 +899,7 @@ Steve Hay E<lt>shay@cpan.orgE<gt>
=head1 COPYRIGHT
-Copyright (C) 2004-2009, 2012-2013 Steve Hay. All rights reserved.
+Copyright (C) 2004-2009, 2012-2014 Steve Hay. All rights reserved.
=head1 LICENCE
@@ -906,11 +909,11 @@ License or the Artistic License, as specified in the F<LICENCE> file.
=head1 VERSION
-Version 2.03
+Version 2.04
=head1 DATE
-08 Jul 2013
+19 Feb 2014
=head1 HISTORY
@@ -1,6 +1,6 @@
________________________________________________________________________________
- Filter::Crypto, Version 2.03
+ Filter::Crypto, Version 2.04
________________________________________________________________________________
PREREQUISITES
@@ -1,6 +1,6 @@
________________________________________________________________________________
- Filter::Crypto, Version 2.03
+ Filter::Crypto, Version 2.04
________________________________________________________________________________
This distribution is free software; you can redistribute it and/or modify it
@@ -54,4 +54,4 @@ requires:
perl: 5.6.0
resources:
license: http://dev.perl.org/licenses/
-version: 2.03
+version: 2.04
@@ -1,6 +1,6 @@
________________________________________________________________________________
- Filter::Crypto, Version 2.03
+ Filter::Crypto, Version 2.04
________________________________________________________________________________
NAME
@@ -93,7 +93,7 @@ INSTALLATION
COPYRIGHT
- Copyright (C) 2004-2010, 2012-2013 Steve Hay. All rights reserved.
+ Copyright (C) 2004-2010, 2012-2014 Steve Hay. All rights reserved.
LICENCE
@@ -29,7 +29,7 @@ use warnings;
our($VERSION);
BEGIN {
- $VERSION = '2.03';
+ $VERSION = '2.04';
}
1;
@@ -270,7 +270,7 @@ Steve Hay E<lt>shay@cpan.orgE<gt>
=head1 COPYRIGHT
-Copyright (C) 2004-2010, 2012-2013 Steve Hay. All rights reserved.
+Copyright (C) 2004-2010, 2012-2014 Steve Hay. All rights reserved.
=head1 LICENCE
@@ -280,11 +280,11 @@ License or the Artistic License, as specified in the F<LICENCE> file.
=head1 VERSION
-Version 2.03
+Version 2.04
=head1 DATE
-08 Jul 2013
+19 Feb 2014
=head1 HISTORY
@@ -8,7 +8,7 @@
# still runnable, format to hide the source code from casual prying eyes.
#
# COPYRIGHT
-# Copyright (C) 2004-2006, 2012 Steve Hay. All rights reserved.
+# Copyright (C) 2004-2006, 2012, 2014 Steve Hay. All rights reserved.
#
# LICENCE
# You may distribute under the terms of either the GNU General Public License
@@ -43,6 +43,7 @@ use constant WARNING_TYPE_SEVERE => 1;
sub get_input_files($$$);
sub resolve_file_expr($$);
+sub show_result();
sub show_warning($$$@);
sub exit_with_version();
sub exit_with_help();
@@ -54,8 +55,8 @@ sub exit_with_error(@);
# INITIALIZATION
#===============================================================================
-our $VERSION = '1.03';
-our $YEAR = '2004-2006, 2012';
+our $VERSION = '1.04';
+our $YEAR = '2004-2006, 2012, 2014';
#===============================================================================
# MAIN PROGRAM
@@ -187,15 +188,7 @@ MAIN: {
binmode STDIN;
if (crypt_file(\*STDIN, $out_file, $crypt_mode)) {
- unless ($silent) {
- print STDERR "OK";
-
- # There may be a message left in $ErrStr even after crypt_file()
- # completes successfully, so output that too if there is.
- print STDERR " ($ErrStr)" if $ErrStr ne '';
-
- print STDERR "\n";
- }
+ show_result() unless $silent;
}
else {
show_warning($silent, WARNING_TYPE_SEVERE, '-',
@@ -273,7 +266,10 @@ MAIN: {
($temp_fh, $temp_file) =
File::Temp::tempfile("$file.XXXXXXXX");
- unless (crypt_file($file, $temp_fh, $crypt_mode)) {
+ my $num_bytes =
+ crypt_file($file, $temp_fh, $crypt_mode);
+
+ unless (defined $num_bytes) {
show_warning($silent, WARNING_TYPE_SEVERE, $file,
"crypt_file() failed: %s", $ErrStr
);
@@ -289,6 +285,23 @@ MAIN: {
);
}
+ # If no output was written because the file was already
+ # in the requested state then just remove the temporary
+ # file; there is nothing more to do.
+ if ($num_bytes == 0 and
+ ($crypt_mode == CRYPT_MODE_ENCRYPTED or
+ $crypt_mode == CRYPT_MODE_DECRYPTED))
+ {
+ show_result() unless $silent;
+ unless (unlink $temp_file) {
+ show_warning($silent, WARNING_TYPE_NORMAL,
+ $file, "Can't delete temporary file " .
+ "'%s': %s", $temp_file, $!
+ );
+ }
+ next;
+ }
+
# Get the input file's permissions and set them on the
# temporary file, so that when it is renamed to the
# input file the new input file has the same permissions
@@ -356,15 +369,7 @@ MAIN: {
}
}
- unless ($silent) {
- print STDERR "OK";
-
- # There may be a message left in $ErrStr even after crypt_file()
- # completes successfully, so output that too if there is.
- print STDERR " ($ErrStr)" if $ErrStr ne '';
-
- print STDERR "\n";
- }
+ show_result() unless $silent;
}
}
@@ -474,13 +479,23 @@ sub resolve_file_expr($$) {
return $new_file;
}
+sub show_result() {
+ print STDERR "OK";
+
+ # There may be a message left in $ErrStr even after crypt_file() completes
+ # successfully, so output that too if there is.
+ print STDERR " ($ErrStr)" if $ErrStr ne '';
+
+ print STDERR "\n";
+}
+
sub show_warning($$$@) {
my($silent, $type, $file, $msg) = splice @_, 0, 4;
$msg = sprintf $msg, @_ if @_;
my $hdr = '';
- $hdr = "$file: " if $silent;
+ $hdr = "$file: " unless $silent;
if ($type == WARNING_TYPE_NORMAL) {
$hdr .= "Warning: ";
}
@@ -945,9 +960,10 @@ given.
=item Can't delete temporary file '%s': %s
(W) The specified temporary file could not be deleted during the clean up of
-temporary files just before exiting when a SIGINT has been caught. The system
-error message corresponding to the standard C library C<errno> variable is also
-given.
+temporary files just before exiting when a SIGINT has been caught, or when
+removing an unneeded temporary file when an input file was found to already be
+in the requested state. The system error message corresponding to the standard
+C library C<errno> variable is also given.
=item Can't open list file '%s' for reading: %s
@@ -1098,7 +1114,7 @@ Steve Hay E<lt>shay@cpan.orgE<gt>
=head1 COPYRIGHT
-Copyright (C) 2004-2006, 2012 Steve Hay. All rights reserved.
+Copyright (C) 2004-2006, 2012, 2014 Steve Hay. All rights reserved.
=head1 LICENCE
@@ -1108,11 +1124,11 @@ License or the Artistic License, as specified in the F<LICENCE> file.
=head1 VERSION
-Version 1.03
+Version 1.04
=head1 DATE
-20 Mar 2012
+19 Feb 2014
=head1 HISTORY
@@ -7,7 +7,7 @@
# Test script to check crypt_file script (and decryption filter).
#
# COPYRIGHT
-# Copyright (C) 2004-2007, 2009 Steve Hay. All rights reserved.
+# Copyright (C) 2004-2007, 2009, 2014 Steve Hay. All rights reserved.
#
# LICENCE
# You may distribute under the terms of either the GNU General Public License
@@ -49,7 +49,7 @@ BEGIN {
$lib_dir = catfile($top_dir, 'blib', 'lib', 'Filter', 'Crypto');
if (-f catfile($lib_dir, 'CryptFile.pm')) {
- plan tests => 99;
+ plan tests => 105;
}
else {
plan skip_all => 'CryptFile component not built';
@@ -557,7 +557,21 @@ MAIN: {
}
qx{$perl $crypt_file -i -c encrypted $iofile 2>$null};
- is($?, 0, 'crypt_file ran OK with -c encrypted option');
+ is($?, 0, 'crypt_file ran OK with -c encrypted option (working in memory)');
+
+ open $fh, $iofile or die "Can't read file '$iofile': $!\n";
+ $contents = do { local $/; <$fh> };
+ close $fh;
+ like($contents, $qrhead, '... and left file encrypted');
+
+ SKIP: {
+ skip 'Decrypt component not built', 1 unless $have_decrypt;
+ chomp($line = qx{$perl $iofile});
+ is($line, $str, '... and encrypted file still runs OK');
+ }
+
+ qx{$perl $crypt_file -i -e tempfile -c encrypted $iofile 2>$null};
+ is($?, 0, 'crypt_file ran OK with -c encrypted option (using a tempfile)');
open $fh, $iofile or die "Can't read file '$iofile': $!\n";
$contents = do { local $/; <$fh> };
@@ -571,7 +585,7 @@ MAIN: {
}
qx{$perl $crypt_file -i -c decrypt $iofile 2>$null};
- is($?, 0, 'crypt_file ran OK with -c decrypt');
+ is($?, 0, 'crypt_file ran OK with -c decrypt option');
open $fh, $iofile or die "Can't read file '$iofile': $!\n";
$contents = do { local $/; <$fh> };
@@ -582,7 +596,18 @@ MAIN: {
is($line, $str, '... and decrypted file runs OK');
qx{$perl $crypt_file -i -c decrypted $iofile 2>$null};
- is($?, 0, 'crypt_file ran OK with -c decrypted');
+ is($?, 0, 'crypt_file ran OK with -c decrypted option (working in memory)');
+
+ open $fh, $iofile or die "Can't read file '$iofile': $!\n";
+ $contents = do { local $/; <$fh> };
+ close $fh;
+ is($contents, $prog, '... and left file decrypted');
+
+ chomp($line = qx{$perl $iofile});
+ is($line, $str, '... and decrypted file still runs OK');
+
+ qx{$perl $crypt_file -i -e tempfile -c decrypted $iofile 2>$null};
+ is($?, 0, 'crypt_file ran OK with -c decrypted option (using a tempfile)');
open $fh, $iofile or die "Can't read file '$iofile': $!\n";
$contents = do { local $/; <$fh> };