Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
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 drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2021-01-23 21:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?