dtrx-py / dtrx

Do The Right Extraction
GNU General Public License v3.0
224 stars 10 forks source link

dtrx doesn't error on missing passwords in non-interactive mode #52

Open sr-verde opened 1 year ago

sr-verde commented 1 year ago

What happens:

dtrx doesn't error on missing passwords on rar archives. I have a password protected archive containing one file file1.txt. When trying to extract the file, I’ll get a password prompt (that will be killed immediately) and after that there is a dir password-protected that contains one empty file.

What I expect:

dtrx should print an error "cannot extract encrypted archive" (as when trying to extract other archive types).

How can you reproduce it:

  1. Create a password protected RAR archive containing a file
  2. Extract it in non-interactive mode

My log:

$ ls
password-protected.rar
$ dtrx -n password-protected.rar 

Enter password (will not be echoed) for file1.txt: %                                             
$ ls 
password-protected  password-protected.rar
$ ls password-protected
file1.txt
$ cat password-protected/file1.txt 
$ 
sr-verde commented 1 year ago

Can be fixed using the is_fatal_error fct of ZIP for the UnarchiverExtractor:

class UnarchiverExtractor(NoPipeExtractor):                                            
    file_type = "RAR archive"                      
    list_command = ["lsar"]                                                

    @property                                         
    def extract_command(self):                                             
        """                                      
        Returns the extraction command and adds a password if given.
        """                           
        cmd = ["unar", "-D"]                                 
        if self.password:                  
            cmd.append("-p %s" % (self.password,))          
        return cmd                                               

    def get_filenames(self):                                                       
        output = NoPipeExtractor.get_filenames(self)
        next(output)                                    
        for line in output:                                           
            end_index = line.rfind("(")                   
            yield line[:end_index].strip()                                   

    def is_fatal_error(self, status):                   
        return (status or 0) > 1