Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Perl wrapper for unrar.dll

by nikosv (Chaplain)
on Mar 19, 2009 at 11:09 UTC ( #751675=sourcecode: print w/replies, xml ) Need Help??
Category: Win32 Stuff
Author/Contact Info nikosv01@gmail.com
Description: The unrar.dll library is written in C and provides functions for extracting/uncompressing rar archives. In the developer distribution there are code examples on interfacing with the library in many languages but not in Perl, so I wrote one which is going to be included in the development edition after Winrar 3.9 gets released. It offers an example of Perl interfacing with C libraries, mapping C structures to Perl structures, using raw pointers from Perl and how to use of Win32 low level API calls. To use it you need to : 1. have the Win32::API module installed 2. get unrar.dll from http://www.rarlab.com/rar/UnRARDLL.exe and place it inside your Windows\System32 directory 3.run it as : for listing the contents of the file : perl unrar_wrapper.pl L filename.rar for extracting contents of file : perl unrar_wrapper.pl X filename.rar Any suggestions/comments/corrections are welcome
#Wrapper for unrar.dll in Perl.Interacts with dll using the Win32::API
+ module
#To do for next version : better error description instead of just 'dy
+ing'
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,$CmtB
+uf,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 "RARO
+penArchive failed";
         
    $flagsEX  & 128 || !$RARReadHeader->Call($handle,$RARHeaderData) |
+| die "RARCloseArchive failed";
   
   
    
    my ($arcname,$filename,$flags,$packsize)=unpack('A260A260LL',$RARH
+eaderData);


    
   $CmtBuf1=unpack('A'.$CmtSize,$CmtBuf1);
   printf("\nComments :%s\n",$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\n\n",($flagsEX  & 256) ? "yes":"no or ol
+der than 3.0");

 !$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,unde
+f,2,0,undef,0,0,0,0);
my $handle = $RAROpenArchiveEx->Call($RAROpenArchiveDataEx_for_extract
+ing)||die "RAROpenArchiveEx failed"; 
my $RARHeaderData=pack('x260x260LLLLLLLLLLpLL',0,0,0,0,0,0,0,0,0,0,0,u
+ndef,0,0,0); 

if ($blockencrypted){
    print ("Encrypted headers,enter password: "),chomp ($password=<STD
+IN>);
    
    if ($password) {
        $RARSetPassword->Call($handle,$password);
    }
    else {
    die "\nshould had entered password!!exiting....\n";
    }
}

    while (($RARReadHeader->Call($handle,$RARHeaderData))==0) {
                           my $processresult=$RARProcessFile->Call($ha
+ndle,0,undef,undef);
                        if ($processresult!=0) {
                           last;
                    }  
                    else {
                       my  @files=unpack('A260A260LLLLLLLLLLpLL',$RARH
+eaderData);
                                        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,unde
+f,1,0,undef,0,0,0,0);
my $RARHeaderData=pack('x260x260LLLLLLLLLLpLL',0,0,0,0,0,0,0,0,0,0,0,u
+ndef,0,0);
 
my $handle = $RAROpenArchiveEx->Call($RAROpenArchiveDataEx_for_extract
+ing)||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($h
+andle,2,undef,undef);
                        if ($processresult!=0) {
                                        $errorstatus=$processresult;
                           last;
                    }          
                     
   }

print "#Error# : $errorstatus" if $errorstatus;
!$RARCloseArchive->Call($handle)||die "RRARCloseArchive failed"; 
}

my $file;
if ($ARGV[1]) {
    $file=$ARGV[1]; }
else {
    print ("No filename!") && exit;
    }

declare_win32_functions();

if ($ARGV[0] eq "L") {
                          list_files_in_archive($file);
                          }
elsif ($ARGV[0] eq "X") {
                          process_file($file);
                          }
else {
            print "Enter mode L or X\n";
        }
Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: sourcecode [id://751675]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2020-09-22 22:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    If at first I donít succeed, I Ö










    Results (130 votes). Check out past polls.

    Notices?