174 lines
6.0 KiB
Perl
174 lines
6.0 KiB
Perl
#Author : Nikos Vaggalis
|
|
#Website : http://perlingresprogramming.blogspot.com/
|
|
#Email : nikos.vaggalis@gmail.com
|
|
#Version Date: 16-11-2008
|
|
#To do for next version : better error description instead of just 'dying' plus more informative messages
|
|
# add support for using script on files not in script's directory
|
|
# comment code
|
|
#Wrapper for unrar.dll in Perl.Interacts with dll using the Win32::API module
|
|
#For feedback/comments/suggestions please use above email address
|
|
|
|
use Win32::API;
|
|
use Cwd;
|
|
|
|
sub declare_win32_functions {
|
|
$RAROpenArchiveEx=new Win32::API('unrar.dll','RAROpenArchiveEx','P','N');
|
|
$RARCloseArchive=new Win32::API('unrar.dll','RARCloseArchive','N','N');
|
|
$RAROpenArchive=new Win32::API('unrar.dll','RAROpenArchive','P','N');
|
|
$RARReadHeader=new Win32::API('unrar.dll','RARReadHeader','NP','N');
|
|
$RARReadHeaderEx=new Win32::API('unrar.dll','RARReadHeaderEx','NP','N');
|
|
$RARProcessFile=new Win32::API('unrar.dll','RARProcessFile','NNPP','N');
|
|
$RARSetPassword=new Win32::API('unrar.dll','RARSetPassword','NP','N');
|
|
}
|
|
|
|
|
|
sub extract_headers {
|
|
my $file=@_[0];
|
|
my $CmtBuf = pack('x16384');
|
|
|
|
my $RAROpenArchiveDataEx=pack('ppLLPLLLLx32',$file,undef,2,0,$CmtBuf,16384,0,0,0);
|
|
my $RAROpenArchiveData=pack('pLLpLLL',$file,2,0,undef,0,0,0);
|
|
my $RARHeaderData=pack('x260x260LLLLLLLLLLpLL',0,0,0,0,0,0,0,0,0,0,0,undef,0,0);
|
|
|
|
my $handle = $RAROpenArchiveEx->Call($RAROpenArchiveDataEx)||die "RAROpenArchiveEx failed";
|
|
|
|
my ($arcname,undef,undef,undef,$CmtBuf1,undef,$CmtSize,$CmtState,$flagsEX)=unpack('ppLLP16384LLLLL',$RAROpenArchiveDataEx);
|
|
|
|
|
|
!$RARCloseArchive->Call($handle)||die "RARCloseArchive failed";
|
|
|
|
my $handle = $RAROpenArchive->Call($RAROpenArchiveData)||die "RAROpenArchive failed";
|
|
|
|
$flagsEX & 128 || !$RARReadHeader->Call($handle,$RARHeaderData) || die "RARCloseArchive failed";
|
|
#!$RARReadHeader->Call($handle,$RARHeaderData)||die "RARReadHeader failed";
|
|
|
|
|
|
my ($arcname,$filename,$flags,$packsize)=unpack('A260A260LL',$RARHeaderData);
|
|
|
|
|
|
|
|
if ($CmtBuf1) {
|
|
$CmtBuf1=unpack('A'.$CmtSize,$CmtBuf1);
|
|
}
|
|
|
|
|
|
printf("\nArchive %s\n",$arcname);
|
|
printf("\nVolume:\t\t%s",($flagsEX & 1) ? "yes":"no");
|
|
printf("\nComment:\t%s",($flagsEX & 2) ? "yes":"no");
|
|
printf("\nLocked:\t\t%s",($flagsEX & 4) ? "yes":"no");
|
|
printf("\nSolid:\t\t%s",($flagsEX & 8) ? "yes":"no");
|
|
printf("\nNew naming:\t%s",($flagsEX & 16) ? "yes":"no");
|
|
printf("\nAuthenticity:\t%s",($flagsEX & 32) ? "yes":"no");
|
|
printf("\nRecovery:\t%s",($flagsEX & 64) ? "yes":"no");
|
|
printf("\nEncr.headers:\t%s",($flagsEX & 128) ? "yes":"no");
|
|
printf("\nFirst volume:\t%s",($flagsEX & 256) ? "yes":"no or older than 3.0");
|
|
printf("\n\nComments :\n%s",$CmtBuf1) if ($CmtBuf1);
|
|
print "\n\n";
|
|
|
|
!$RARCloseArchive->Call($handle);
|
|
return ($flagsEX & 128,$flags & 4);
|
|
|
|
}
|
|
|
|
sub list_files_in_archive {
|
|
my $file =@_[0];
|
|
my ($blockencrypted,$locked) = extract_headers($file);
|
|
|
|
my $password;
|
|
|
|
my $RAROpenArchiveDataEx_for_extracting=pack('ppLLpLLLLx32',$file,undef,2,0,undef,0,0,0,0);
|
|
my $handle = $RAROpenArchiveEx->Call($RAROpenArchiveDataEx_for_extracting)||die "RAROpenArchiveEx failed";
|
|
my $RARHeaderData=pack('x260x260LLLLLLLLLLpLL',0,0,0,0,0,0,0,0,0,0,0,undef,0,0,0);
|
|
|
|
if ($blockencrypted){
|
|
print ("Encrypted headers,enter password: "),chomp ($password=<STDIN>);
|
|
|
|
if ($password) {
|
|
$RARSetPassword->Call($handle,$password);
|
|
}
|
|
else {
|
|
die "\nshould had entered password!!exiting....\n";
|
|
}
|
|
}
|
|
|
|
while (($RARReadHeader->Call($handle,$RARHeaderData))==0) {
|
|
my $processresult=$RARProcessFile->Call($handle,0,undef,undef);
|
|
if ($processresult!=0) {
|
|
last;
|
|
}
|
|
else {
|
|
my @files=unpack('A260A260LLLLLLLLLLpLL',$RARHeaderData);
|
|
print "File\t\t\t\t\tSize\n";
|
|
print "-------------------------------------------\n";
|
|
print "$files[0]\\$files[1]\t\t$files[4]\n\n";
|
|
}
|
|
|
|
}
|
|
|
|
|
|
!$RARCloseArchive->Call($handle)||die "$RARCloseArchive failed";
|
|
}
|
|
|
|
sub process_file {
|
|
my $file=@_[0];
|
|
my ($blockencrypted,$locked) = extract_headers($file);
|
|
|
|
my $errorstatus;
|
|
my $password;
|
|
|
|
my $RAROpenArchiveDataEx_for_extracting=pack('ppLLpLLLLx32',$file,undef,1,0,undef,0,0,0,0);
|
|
my $RARHeaderData=pack('x260x260LLLLLLLLLLpLL',0,0,0,0,0,0,0,0,0,0,0,undef,0,0);
|
|
|
|
my $handle = $RAROpenArchiveEx->Call($RAROpenArchiveDataEx_for_extracting)||die "RAROpenArchiveEx failed";
|
|
|
|
if ($blockencrypted || $locked){
|
|
print ("Enter password: "),chomp ($password=<STDIN>);
|
|
|
|
if ($password) {
|
|
$RARSetPassword->Call($handle,$password);
|
|
}
|
|
else {
|
|
die "\nshould had entered password!!exiting....\n";
|
|
}
|
|
}
|
|
|
|
|
|
while (($RARReadHeader->Call($handle,$RARHeaderData))==0) {
|
|
my $processresult=$RARProcessFile->Call($handle,2,undef,undef);
|
|
if ($processresult!=0) {
|
|
$errorstatus=$processresult;
|
|
last;
|
|
}
|
|
|
|
}
|
|
|
|
print "Errorstatus : $errorstatus " if $errorstatus;
|
|
!$RARCloseArchive->Call($handle)||die "RRARCloseArchive failed";
|
|
}
|
|
|
|
declare_win32_functions();
|
|
|
|
my $file;
|
|
if (!defined @ARGV) {
|
|
print "Usage : perl unrar.pl [option] filename\n";
|
|
print "where [option] is either X or L. (X=extract,L=List file contents)\n";
|
|
print "\nThe script and the file to be processed should be in the same directory\n";
|
|
print "\nExample usage: \nperl unrar.pl L myfile.rar\n";
|
|
}
|
|
elsif (!defined $ARGV[0] || $ARGV[0] ne "L" && $ARGV[0] ne "X") {
|
|
print "Enter mode L or X\n";
|
|
}
|
|
elsif (!defined $ARGV[1]) {
|
|
print ("No filename!") && exit;
|
|
}
|
|
else {
|
|
$file=$ARGV[1];
|
|
if ($ARGV[0] eq "L") {
|
|
list_files_in_archive($file);
|
|
}
|
|
elsif ($ARGV[0] eq "X") {
|
|
process_file($file);
|
|
}
|
|
}
|
|
|