25 Dec 2011

List all installed and available Perl modules

Code below provides list of modules which perl interpreter can find in runtime.

Code

#!/usr/bin/perl
#
# Author:  Tomasz Gaweda
# Date:    2011.12.23 17:00
# Purpose: Print all modules installed 
#          in perl distribution
#
# Usage:   perl showmodules.pl

use strict;
use warnings;
use File::Find;

my @modules;
my $IgnorePatt = join("|",@INC) ;#$IgnorePatt =~ s/\|\.// ;
find(
 sub {
  my $f = $File::Find::name;
  if ( $f =~ s/^(${IgnorePatt})\/(.*?)\.pm$/$2/ ) 
  {
   $f =~ s/[\/\\]/::/g;
   push @modules, $f;
  }
 }
 , grep { -d } @INC
);
print "There are [".scalar(@modules)."] modules that perl can locate on runtime...\n";
print "Printing List in Minute\n" ;
sleep 3;
print join("\n", sort{ lc $a cmp lc $b} @modules)."\n";

Sample output

There are [2346] modules that perl can locate on runtime...
Printing List in Minute
AcidRip::acidrip
AcidRip::interface
AcidRip::messages
AcidRip::signals
AE
Algorithm::C3
Algorithm::Diff
Algorithm::Diff::XS
Algorithm::DiffOld
Algorithm::Merge
Alien::Package
...

11 Dec 2011

Encoding files "on the fly" with Blowfish using Perl

Some time ago friend of mine asked me if I could write him an CGI script which encodes his backup file and allows to download it using HTTP protocol.

He is using some kind of VPS so my CGI app had some limitations:

  • file must be encoded "on the fly" to save disk space (no temporary files)
  • encoding should be memmory efficient - because VPS hasn't got very much RAM and backup files are quite large
  • encoding should be fast - so the best solution would be using XS module

After some research I've created this two scripts:

Warning: Scripts depends on external Perl modules which are available at CPAN and in Debian repository.
apt-get install libcrypt-cbc-perl libcrypt-blowfish-perl

Blowfish CGI encoding using Perl

#!/usr/bin/perl

use strict;
use warnings;

use CGI;
use HTML::Entities;
use Crypt::CBC;
use File::Spec;

my $as_cgi = 1; # if run from apachce set to 1 if CLI 0

my $key = "ala_ma_kota.123";
my $fName = './large_file.bin';

my $chunkSize = 1024;
my $out_FName = 'out.bin';



if ( $as_cgi ) {
 print "Content-Type:application/octet-stream; name=\"".$out_FName."\"\r\n";
 print "Content-Disposition: attachment; filename=\"".$out_FName."\"\r\n\n";
}

my $buffer = '';
my $cipher = Crypt::CBC->new( 
   -key    => $key,
   -cipher => 'Blowfish',
);

die "Unable to find file $fName\n" if not -e $fName;


open(ENCODEME, '<:raw', $fName) or die "$!";
binmode ENCODEME;
$cipher->start('encrypting');
while( read(ENCODEME,$buffer,$chunkSize) ) {
 print $cipher->crypt($buffer);
}
print $cipher->finish;
close(ENCODEME);

Blowfish decoding file using Perl

 #!/usr/bin/perl

# apt-get install libcrypt-cbc-perl
# apt-get install libcrypt-blowfish-perl

use strict;
use warnings;

use Crypt::CBC;
use File::Spec;

my $key = "ala_ma_kota.123";
my $chunkSize = 1024;

my $fName = 'zz.bin';

my $buffer = '';
my $cipher = Crypt::CBC->new( 
   -key    => $key,
   -cipher => 'Blowfish',
);

#$fName = File::Spec->catfile($base_dir, $fName);
die "Unable to find file $fName\n" if not -e $fName;


open(ENCODEME, '<:raw', $fName) or die "$!";
binmode ENCODEME;
$cipher->start('decrypting');
while( read(ENCODEME,$buffer,$chunkSize) ) {
 print $cipher->crypt($buffer);
}
print $cipher->finish;
close(ENCODEME);

13 Oct 2011

Using perl to extract files from large directory structure

When I work on Windows I use Activesite Active Perl to do some stuff. Recently I had to copy about 60 files from large directory structure to a new place (about 800 files in nasty directory structure). It was rather boring stuff to do, so I used perl to finish job because it would be pretty easy task to do using hashes (I had names of files given in text file). Unfortunately I had some problems on completion of job, because there was a problem with encoding of file path name on Windows.

Below I provide simple script demonstration how to handle national characters in path using perl on Windows.

#!/usr/bin/perl
 
use strict;
use warnings;
 
use utf8;
use Encoding;
 
# Win32::Codepage::Simple is available in ActiveState Perl
use Win32::Codepage::Simple qw(get_codepage get_acp);
use File::Find;
use File::Copy;
use File::Path;
use File::Basename;
 
binmode STDOUT, ":utf8";
binmode STDERR, ":utf8";
 
my $dir  = "./copy_from_here/";
my $dest = "./copy_here/";
my %filter = ( 'grzegrzółka.doc' => 1, 'słoń i łoś.avi' => 1);
 
# Polish Windows 7 :)
my $encoding = get_codepage();
if ($encoding eq '1250') {
   $encoding = 'cp1250';
}
 
find(
       { wanted =>
               sub {
 
               return if not -f $File::Find::name;
 
               my $mfname = $encoding ? 
                              decode($encoding, $File::Find::name) 
                            : $File::Find::name;
               return if not exists $filter{$mfname};
 
               my $nfile = basename($File::Find::name);
               if ( not -e $dest.'/'.$nfile ) {
                       copy($fInName, $dest.'/'.$nfile) or die "File cannot be copied.";
               } else {
                       print "File exists: ".$nfile."\n";
               }
 
               },
       follow => 1, no_chdir => 1, depth => 1
       }
       , $dir
);

More information about national characters in path on Windows