U
    cyh,                    @   s  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
mZ ddlmZmZ ddlmZmZmZmZ ddlmZ ddlmZmZmZ ddlmZmZmZmZ dd	lmZ dZzTz(dd
l m!Z! ddl"m#Z#m$Z$m%Z% dZ&W n& e'k
r   ddl(mZ dZ&Y nX W n e'k
r2   dZ&Y nX G dd dZ)dZ*ddddddgZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5d Z6d!Z7d"Z8d#Z9d$Z:d%Z;d&Z<d'Z=d(Z>d)Z?d*Z@dZAdZBd+ZCd,ZDd-ZEd.ZFd/ZGd0ZHd1ZId2ZJdZKdZLd+ZMd,ZNd-ZOd3ZPdZQd.ZRd/ZSd4ZTd0ZUd5ZVd6ZWd3ZXd1ZYd2ZZd7Z[d8Z\d9Z]d:Z^dZ_dZ`d+Zad,Zbd;Zcd<ZddZedZfdZgd=Zhd+Zid>Zjd?Zkd@ZldAZmdBZndCZodDZpdZqdZrd=Zsd+Ztd>ZudZvdZwd+Zxd,Zyd-Zzd.Z{d/Z|dZ}dZ~d+Zd,Zd-ZdZdZd+Zd,Zd/ZdZdZdZdZd=Zd+Zd>ZdEZdFZdZdZd+Zd,Zd-ZdZdZdZdZdZdZd=Zd+Zd>ZdZdZdZd+Zd,ZdZdZd.Zd-Zd+ZdZdZd,Zd+ZdGZdHZejdIkZerrdJndKZdLZd=Zd>ZdMZedNe ZedOe ZdPZdQdR ZdSd ZdTd ZdUd ZG dVdW dWeZG dXdY dYeZG dZd[ d[eZG d\d] d]eZG d^d_ d_eZG d`da daeZG dbdc dceZG ddde deeZG dfdg dgeZG dhdi dieƃZG djdk dkeƃZG dldm dmeƃZG dndo doeƃZG dpdq dqeƃZG drds dseƃZG dtdu dueƃZG dvdw dweƃZG dxdy dyeƃZG dzd{ d{eƃZG d|d} d}eƃZG d~d deƃZG dd deƃZG dd deƃZG dd deƃZG dd deփZG dd dZG dd dZG dd dZG dd de؃ZG dd deڃZG dd de؃ZG dd de݃ZG dd deރZG dd deރZG dd de݃ZG dd de݃ZG dd de݃ZG dd deڃZG dd dZG dd dejZG dd deZG dd deZG dd dZG dd dZG dd dZG dd dZG dd dZG dd dZedZedZedZedZedZedZdd Zdd Zdd Zdd Zdd ZddĄ ZddƄ ZddȄ ZedɡZdd˄ Zdd̈́ Z ddτ Zddф ZdddӄZddՄ Zddׄ ZdddلZddۄ Zdd݄ Zdd߄ Z	dd Z
G dd deZdd Zdd Zdd Zdd Zdd ZG dd dZdddddeeeeeeeeeeegdZdddddgdZdddddgdZdddddeeddddeeg	dZdddddeeddddeeg	dZdadddZdd Zedkreejdd  dS (	  a  RAR archive reader.

This is Python module for Rar archive reading.  The interface
is made as :mod:`zipfile`-like as possible.

Basic logic:
 - Parse archive structure with Python.
 - Extract non-compressed files with Python
 - Extract compressed files with unrar.
 - Optionally write compressed data to temp file to speed up unrar,
   otherwise it needs to scan whole archive on each execution.

Example::

    import rarfile

    rf = rarfile.RarFile("myarchive.rar")
    for f in rf.infolist():
        print(f.filename, f.file_size)
        if f.filename == "README":
            print(rf.read(f))

Archive files can also be accessed via file-like object returned
by :meth:`RarFile.open`::

    import rarfile

    with rarfile.RarFile("archive.rar") as rf:
        with rf.open("README") as f:
            for ln in f:
                print(ln.strip())

For decompression to work, either ``unrar`` or ``unar`` tool must be in PATH.
    N)crc32hexlify)datetimetimezone)blake2spbkdf2_hmacsha1sha256)Path)Structpackunpack)DEVNULLPIPESTDOUTPopen)mkstemp)default_backend)Cipher
algorithmsmodes   )AES   c                   @   s   e Zd ZdZdd ZdS )AES_CBC_DecryptzDecrypt APIc                 C   sH   t dkrt|tj|j| _n&tt|t|t	 }|
 j| _d S )Nr   )_have_cryptor   newZMODE_CBCdecryptr   r   r   ZCBCr   Z	decryptorupdate)selfkeyivciph r#   1/usr/local/lib/python3.8/dist-packages/rarfile.py__init__W   s    zAES_CBC_Decrypt.__init__N)__name__
__module____qualname____doc__r%   r#   r#   r#   r$   r   U   s   r   z4.2get_rar_version
is_rarfileis_rarfile_sfxRarInfoRarFile
RarExtFileunrarunarbsdtarZ7zZ7zzzwindows-1252)utf8utf-16lei  @/r   s   t   u   v   w   x   y   z   {                @         i      `            i   i        @  i         0   1   2   3   4   5         s   Rar! s   Rar! win32i   i       z\x00-\x1F<>|"?*z[%s]z[%s:^\\]Fc           
   
   C   s   t d d }t }dtf}t| }|D ]}||}|s@ q|| | }d}|||}	|	dk rlq*||	|	t	t   t krt
|	f  W  5 Q R  S ||	|	t	t  tkrt|	f  W  5 Q R  S |	t	| }qVq*W 5 Q R X dS )NrD   r   )r   r   )RAR_IDioBytesIOSFX_MAX_SIZEXFilereadwritegetvaluefindlenRAR_V3RAR5_IDRAR_V5)
xfilesigbufZstepsfdstepdataZcurdataZfindposposr#   r#   r$   _find_sfx_header;  s(    


ro   c              	   C   sB   t | }|tt}W 5 Q R X |tr0tS |tr>tS dS )/Check quickly whether file is rar archive.
    r   )r_   r`   rd   rf   
startswithr[   re   rg   )rh   rk   rj   r#   r#   r$   r*   Y  s    


c                 C   s*   zt | dkW S  tk
r$   Y dS X dS )rp   r   FN)r*   OSErrorrh   r#   r#   r$   r+   e  s    c                 C   s   t | d dkS )z\Check whether file is rar archive with support for SFX.

    It will read 2M from file.
    r   )ro   rs   r#   r#   r$   r,   o  s    c                   @   s   e Zd ZdZdS )ErrorzBase class for rarfile errors.Nr&   r'   r(   r)   r#   r#   r#   r$   rt   w  s   rt   c                   @   s   e Zd ZdZdS )
BadRarFilezIncorrect data in archive.Nru   r#   r#   r#   r$   rv   {  s   rv   c                   @   s   e Zd ZdZdS )
NotRarFilezThe file is not RAR archive.Nru   r#   r#   r#   r$   rw     s   rw   c                   @   s   e Zd ZdZdS )
BadRarNamez'Cannot guess multipart name components.Nru   r#   r#   r#   r$   rx     s   rx   c                   @   s   e Zd ZdZdS )
NoRarEntryzFile not found in RARNru   r#   r#   r#   r$   ry     s   ry   c                   @   s   e Zd ZdZdS )PasswordRequiredzFile requires passwordNru   r#   r#   r#   r$   rz     s   rz   c                       s    e Zd ZdZ fddZ  ZS )NeedFirstVolumezNeed to start from first volume.

    Attributes:

        current_volume
            Volume number of current file or None if not known
    c                    s   t  | || _d S N)superr%   Zcurrent_volume)r   msgvolume	__class__r#   r$   r%     s    zNeedFirstVolume.__init__)r&   r'   r(   r)   r%   __classcell__r#   r#   r   r$   r{     s   r{   c                   @   s   e Zd ZdZdS )NoCryptoz5Cannot parse encrypted headers - no crypto available.Nru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarExecErrorzProblem reported by unrar/rar.Nru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )
RarWarningzNon-fatal errorNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarFatalErrorzFatal errorNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarCRCErrorzCRC error during unpackingNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarLockedArchiveErrorzMust not modify locked archiveNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarWriteErrorzWrite errorNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarOpenErrorz
Open errorNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarUserErrorz
User errorNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarMemoryErrorzMemory errorNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarCreateErrorzCreate errorNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarNoFilesErrorz&No files that match pattern were foundNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarUserBreakz	User stopNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarWrongPasswordzIncorrect passwordNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarUnknownErrorzUnknown exit codeNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarSignalExitzUnrar exited with signalNru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )RarCannotExeczExecutable not found.Nru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdS )UnsupportedWarningzUArchive uses feature that are unsupported by rarfile.

    .. versionadded:: 4.0
    Nru   r#   r#   r#   r$   r     s   r   c                   @   s   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdZdZdZdZdZdZdZdd Zdd Zdd	 Zd
d Zdd ZdS )r-   a  An entry in rar archive.

    Timestamps as :class:`~datetime.datetime` are without timezone in RAR3,
    with UTC timezone in RAR5 archives.

    Attributes:

        filename
            File name with relative path.
            Path separator is "/".  Always unicode string.

        date_time
            File modification timestamp.   As tuple of (year, month, day, hour, minute, second).
            RAR5 allows archives where it is missing, it's None then.

        comment
            Optional file comment field.  Unicode string.  (RAR3-only)

        file_size
            Uncompressed size.

        compress_size
            Compressed size.

        compress_type
            Compression method: one of :data:`RAR_M0` .. :data:`RAR_M5` constants.

        extract_version
            Minimal Rar version needed for decompressing.  As (major*10 + minor),
            so 2.9 is 29.

            RAR3: 10, 20, 29

            RAR5 does not have such field in archive, it's simply set to 50.

        host_os
            Host OS type, one of RAR_OS_* constants.

            RAR3: :data:`RAR_OS_WIN32`, :data:`RAR_OS_UNIX`, :data:`RAR_OS_MSDOS`,
            :data:`RAR_OS_OS2`, :data:`RAR_OS_BEOS`.

            RAR5: :data:`RAR_OS_WIN32`, :data:`RAR_OS_UNIX`.

        mode
            File attributes. May be either dos-style or unix-style, depending on host_os.

        mtime
            File modification time.  Same value as :attr:`date_time`
            but as :class:`~datetime.datetime` object with extended precision.

        ctime
            Optional time field: creation time.  As :class:`~datetime.datetime` object.

        atime
            Optional time field: last access time.  As :class:`~datetime.datetime` object.

        arctime
            Optional time field: archival time.  As :class:`~datetime.datetime` object.
            (RAR3-only)

        CRC
            CRC-32 of uncompressed file, unsigned int.

            RAR5: may be None.

        blake2sp_hash
            Blake2SP hash over decompressed data.  (RAR5-only)

        volume
            Volume nr, starting from 0.

        volume_file
            Volume file name, where file starts.

        file_redir
            If not None, file is link of some sort.  Contains tuple of (type, flags, target).
            (RAR5-only)

            Type is one of constants:

                :data:`RAR5_XREDIR_UNIX_SYMLINK`
                    Unix symlink.
                :data:`RAR5_XREDIR_WINDOWS_SYMLINK`
                    Windows symlink.
                :data:`RAR5_XREDIR_WINDOWS_JUNCTION`
                    Windows junction.
                :data:`RAR5_XREDIR_HARD_LINK`
                    Hard link to target.
                :data:`RAR5_XREDIR_FILE_COPY`
                    Current file is copy of another archive entry.

            Flags may contain bits:

                :data:`RAR5_XREDIR_ISDIR`
                    Symlink points to directory.
    Nr   c                 C   s   dS )zMReturns True if entry is a directory.

        .. versionadded:: 4.0
        Fr#   r   r#   r#   r$   is_diri  s    zRarInfo.is_dirc                 C   s   dS )zKReturns True if entry is a symlink.

        .. versionadded:: 4.0
        Fr#   r   r#   r#   r$   
is_symlinkp  s    zRarInfo.is_symlinkc                 C   s   dS )zOReturns True if entry is a normal file.

        .. versionadded:: 4.0
        Fr#   r   r#   r#   r$   is_filew  s    zRarInfo.is_filec                 C   s   | j tkr| jt@ dkS dS )z;Returns True if data is stored password-protected.
        r   F)typeRAR_BLOCK_FILEflagsRAR_FILE_PASSWORDr   r#   r#   r$   needs_password~  s    
zRarInfo.needs_passwordc                 C   s   |   S )zKReturns True if entry is a directory.

        .. deprecated:: 4.0
        )r   r   r#   r#   r$   isdir  s    zRarInfo.isdir)r&   r'   r(   r)   filename	file_sizecompress_size	date_timeCRCr   orig_filenamemtimectimeatimeextract_versionmodehost_oscompress_typecommentarctimeblake2sp_hash
file_redirr   r   r   r   r   r   r   r#   r#   r#   r$   r-     s4   bc                   @   s   e Zd ZdZdZdZd=ddZd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd>dd Zd?d!d"Zd#d$ Zd@d%d&ZdAd'd(ZdBd)d*ZdCd+d,Zd-d. Zd/d0 Zd1d2 Zd3d4 Zd5d6 Zd7d8 Zd9d: Zd;d< Z dS )Dr.   a  Parse RAR structure, provide access to files in archive.

    Parameters:

        file
            archive file name or file-like object.
        mode
            only "r" is supported.
        charset
            fallback charset to use, if filenames are not already Unicode-enabled.
        info_callback
            debug callback, gets to see all archive entries.
        crc_check
            set to False to disable CRC checks
        errors
            Either "stop" to quietly stop parsing on errors,
            or "strict" to raise errors.  Default is "stop".
        part_only
            If True, read only single file and allow it to be middle-part
            of multi-volume archive.

            .. versionadded:: 4.0
    NrTstopFc                 C   s   t |rt|dd | _nt|tr*t|}|| _|| _|p<t| _|| _	|| _
|| _d | _d | _|dkrnd| _n|dkr~d| _ntd|dkrtd|   d S )	Nnamer   FstrictTz$Invalid value for errors= parameter.r   zRarFile supports only mode=r)is_filelikegetattrr   
isinstancer
   str_rarfileDEFAULT_CHARSET_charset_info_callback
_crc_check
_part_only	_password_file_parser_strict
ValueErrorNotImplementedError_parse)r   filer   charsetZinfo_callback	crc_checkerrors	part_onlyr#   r#   r$   r%     s(    

zRarFile.__init__c                 C   s   | S )zOpen context.r#   r   r#   r#   r$   	__enter__  s    zRarFile.__enter__c                 C   s   |    dS )zExit context.Nclose)r   typvalue	tracebackr#   r#   r$   __exit__  s    zRarFile.__exit__c                 C   s   t |  S )zIterate over members.)iterinfolistr   r#   r#   r$   __iter__  s    zRarFile.__iter__c                 C   s>   || _ | jr| j rd| _| js,|   n| j| j  dS )z2Sets the password to use when extracting.
        N)r   r   has_header_encryptionr   setpasswordr   pwdr#   r#   r$   r     s    

zRarFile.setpasswordc                 C   s
   | j  S )zMReturns True if any archive entries require password for extraction.
        )r   r   r   r#   r#   r$   r     s    zRarFile.needs_passwordc                 C   s
   | j  S )zWReturns True if archive uses solid compression.

        .. versionadded:: 4.2
        )r   is_solidr   r#   r#   r$   r     s    zRarFile.is_solidc                 C   s   dd |   D S )z-Return list of filenames in archive.
        c                 S   s   g | ]
}|j qS r#   )r   ).0fr#   r#   r$   
<listcomp>  s     z$RarFile.namelist.<locals>.<listcomp>)r   r   r#   r#   r$   namelist  s    zRarFile.namelistc                 C   s
   | j  S )zEReturn RarInfo objects for all files/directories in archive.
        )r   r   r   r#   r#   r$   r     s    zRarFile.infolistc                 C   s
   | j  S )zReturns filenames of archive volumes.

        In case of single-volume archive, the list contains
        just the name of main archive file.
        )r   
volumelistr   r#   r#   r$   r     s    zRarFile.volumelistc                 C   s   | j |S )z!Return RarInfo for file.
        )r   getinfor   r   r#   r#   r$   r     s    zRarFile.getinfoc                 C   s   | j |S )zReturn RarInfo for file source.

        RAR5: if name is hard-linked or copied file,
        returns original entry with original filename.

        .. versionadded:: 4.1
        )r   getinfo_origr   r#   r#   r$   r     s    zRarFile.getinfo_origc                 C   sn   |dkrt d| |}| r2td|j | r\|pB| j}|dkr`td|j nd}| j	
||S )a  Returns file-like object (:class:`RarExtFile`) from where the data can be read.

        The object implements :class:`io.RawIOBase` interface, so it can
        be further wrapped with :class:`io.BufferedReader`
        and :class:`io.TextIOWrapper`.

        On older Python where io module is not available, it implements
        only .read(), .seek(), .tell() and .close() methods.

        The object is seekable, although the seeking is fast only on
        uncompressed files, on compressed files the seeking is implemented
        by reading ahead and/or restarting the decompression.

        Parameters:

            name
                file name or RarInfo instance.
            mode
                must be "r"
            pwd
                password to use for extracting.
        r   z#RarFile.open() supports only mode=rz"Directory does not have any data: NzFile %s requires password)r   r   r   r\   UnsupportedOperationr   r   r   rz   r   open)r   r   r   r   infr#   r#   r$   r     s    

zRarFile.openc              
   C   s.   |  |d|}| W  5 Q R  S Q R X dS )a  Return uncompressed data for archive entry.

        For longer files using :meth:`~RarFile.open` may be better idea.

        Parameters:

            name
                filename or RarInfo instance
            pwd
                password to use for extracting.
        r   N)r   r`   )r   r   r   r   r#   r#   r$   r`   8  s    zRarFile.readc                 C   s   dS )zRelease open resources.Nr#   r   r#   r#   r$   r   H  s    zRarFile.closec                 C   s.   |dkrt j}|  D ]}t|j|d qdS )z9Print archive file list to stdout or given file.
        N)r   )sysstdoutr   printr   )r   r   r   r#   r#   r$   printdirL  s    zRarFile.printdirc                 C   s   |  |}| |||dS )a  Extract single file into current directory.

        Parameters:

            member
                filename or :class:`RarInfo` instance
            path
                optional destination path
            pwd
                optional password to use
        T)r   _extract_one)r   memberpathr   r   r#   r#   r$   extractT  s    
zRarFile.extractc           	      C   s   |dkr|   }t }g }|D ]L}| |}| ||||  }| r||kr|||f || q|r|jdd |D ]\}}| || qdS )a  Extract all files into current directory.

        Parameters:

            path
                optional destination path
            members
                optional filename or :class:`RarInfo` instance list to extract
            pwd
                optional password to use
        NT)reverse)	r   setr   r   r   appendaddsort
_set_attrs)	r   r   membersr   donedirsmr   dstr#   r#   r$   
extractallc  s    
zRarFile.extractallc              
   C   sB   |   D ]4}| r| |d|}t||jt W 5 Q R X qdS )z%Read all files and test CRC.
        r   N)r   r   r   
empty_readr   BSIZE)r   r   r   r   r#   r#   r$   testrar  s    zRarFile.testrarc                 C   s   | j s
dS | j  S )zFReturn error string if parsing failed or None if no problems.
        Not a RAR file)r   strerrorr   r#   r#   r$   r     s    zRarFile.strerrorc              	   C   s   t | j\}}|tkrBt| j| j| j| j| j| j|| j	}|| _
n<|tkrvt| j| j| j| j| j| j|| j	}|| _
ntd| j
  | j
j| _dS )z!Run parser for file type
        r   N)ro   r   re   
RAR3Parserr   r   r   r   r   r   r   rg   
RAR5Parserrw   parser   )r   verZsfx_ofsZp3Zp5r#   r#   r$   r     s,          
zRarFile._parsec                 C   s   t |jtjjt}|d kr$t }n
t|}tj||}tj	|}|rb|dkrbtj
|dd | rz| ||||S | r| ||||S | r| ||||S d S )N.Texist_ok)sanitize_filenamer   osr   sepWIN32getcwdfspathjoindirnamemakedirsr   
_make_filer   	_make_dirr   _make_symlink)r   infor   r   	set_attrsfnamedstfnr
  r#   r#   r$   r     s&      

zRarFile._extract_onec                 C   s   t ||S r|   )r  r   )r   r   r   r  r#   r#   r$   _create_helper  s    zRarFile._create_helperc              
      sb    fdd}  d|,}t |d|d}t|| W 5 Q R X W 5 Q R X |r^ | |S )Nc                    s    | | S r|   )r  )r   r   r  r   r#   r$   helper  s    z"RarFile._make_file.<locals>.helperr   wb)opener)r   shutilcopyfileobjr   )r   r  r  r   r  r  srcr   r#   r  r$   r    s     zRarFile._make_filec                 C   s"   t j|dd |r| || |S )NTr  )r  r  r   )r   r  r  r   r  r#   r#   r$   r    s    zRarFile._make_dirc           	      C   s   d}|j tkr*| ||}|jt@ tk}nX|jrj|j\}}}|tkr\td|j	 t
 d S |t@ dk}ntd|j	 t
 d S tj|||d |S )NFz!Windows junction not supported - r   zUnsupported link type - )target_is_directory)r   RAR_OS_UNIXr`   r   RAR_FILE_DIRECTORYr   RAR5_XREDIR_WINDOWS_JUNCTIONwarningswarnr   r   RAR5_XREDIR_ISDIRr  symlink)	r   r  r  r   r  r  Z	link_name
redir_typeredir_flagsr#   r#   r$   r    s    
zRarFile._make_symlinkc                 C   s   |j tkrt||jd@  nD|j ttfkrb|jt@ rb| sBt	sbt
|}|jd@ }t|| |jrt|j}|jrt|jn|}tj|||fd d S )Ni  im)ns)r   r  r  chmodr   RAR_OS_WIN32RAR_OS_MSDOSDOS_MODE_READONLYr   r  statst_moder   to_nsecsr   utime)r   r  r  stZnew_modeZmtime_nsZatime_nsr#   r#   r$   r     s    



zRarFile._set_attrs)r   NNTr   F)r   N)N)N)NN)NNN)N)!r&   r'   r(   r)   r   r   r%   r   r   r   r   r   r   r   r   r   r   r   r   r`   r   r   r   r   r   r   r   r   r  r  r  r  r   r#   r#   r#   r$   r.     sD         


*





c                   @   s   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdd Zdd Zdd	 Zd
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Z d.d/ Z!d0d1 Z"d4d2d3Z#dS )5CommonParserzShared parser parts.NFc	           	      C   sF   || _ || _|| _|| _|| _|| _g | _i | _g | _|| _	|| _
d S r|   )r   r   r   r   r   r   
_info_list	_info_map	_vol_list_sfx_offsetr   )	r   rarfilepasswordr   r   r   Zinfo_cbZ
sfx_offsetr   r#   r#   r$   r%     s    zCommonParser.__init__c                 C   s   | j r| j jt@ rdS dS )z8Returns True if archive uses solid compression.
        TF)_mainr   RAR_MAIN_SOLIDr   r#   r#   r$   r     s    zCommonParser.is_solidc                 C   s$   | j r
dS | jr | jjt@ r dS dS )z.Returns True if headers are encrypted
        TF)_hdrenc_mainr6  r   RAR_MAIN_PASSWORDr   r#   r#   r$   r     s    z"CommonParser.has_header_encryptionc                 C   s
   || _ dS )zSet cached password.N)r   r   r#   r#   r$   r   "  s    zCommonParser.setpasswordc                 C   s   | j S )zVolume files)r2  r   r#   r#   r$   r   &  s    zCommonParser.volumelistc                 C   s   | j S )zIs password required)_needs_passwordr   r#   r#   r$   r   *  s    zCommonParser.needs_passwordc                 C   s   | j S )z
Last error)_parse_errorr   r#   r#   r$   r   .  s    zCommonParser.strerrorc                 C   s   | j S )z!List of RarInfo records.
        )r0  r   r#   r#   r$   r   2  s    zCommonParser.infolistc                 C   sr   t |tr|j}nt |tr&t|}n|}|dr>|d}z| j| W S  tk
rl   t	d| dY nX dS )z$Return RarInfo for filename
        r5   zNo such file: %sN)
r   r-   r   r
   r   endswithrstripr1  KeyErrorry   )r   r   r  r#   r#   r$   r   7  s    




zCommonParser.getinfoc                 C   s6   |  |}|jr2|j\}}}|ttfkr2|  |}|S r|   )r   r   RAR5_XREDIR_FILE_COPYRAR5_XREDIR_HARD_LINK)r   r   r   r#  r$  
redir_namer#   r#   r$   r   I  s    

zCommonParser.getinfo_origc                 C   s0   d| _ z|   W 5 | j r*| j   d| _ X dS )zProcess file.N)_fdr   _parse_realr   r#   r#   r$   r   R  s    
zCommonParser.parsec           	      C   s  t | j}|| _|| jd |t| j}|| jkr@tdd}d}d}| j}| jg| _	d}|rjd}n
| 
|}|s<|rtdd|r| js|d7 }|  z| |}t |}W n& tk
r   | d| Y qY nX || _|t| j}|| jkr| d| qd}d}| j	| d| _d| _q`q||_||_|jtkr| js|| _|dkr|jt@ r| js|jt@ dkrt|d	ddk	rtd
|jf |jd}|jt@ rdd| _| jsdqn|jt kr&|jt!@ rd}d}|rd|jt"@ dkrdtd
|j#f |j#n>|jt$krd|jt%@ rBd}|dkrd|jt&@ rd| jsdd}|' rtd| _| (|| | j)r| )| |j*dkr`||j+|j* d q`dS )zActually read file.
        r   zNot a Rar archiveFNzNeed to start from first volumer   zCannot open next volume: %szInvalid volume sig: %smain_volume_numberz-Need to start from first volume (current: %r)T),r_   r   rB  seekr3  r`   rd   _expect_sigrw   r2  _parse_headerr{   r   r   _next_volnameIOError
_set_errorr   r6  r8  r   volume_filer   RAR_BLOCK_MAINr   RAR_MAIN_NEWNUMBERINGRAR_MAIN_FIRSTVOLUMEr   rD  r9  r:  r   RAR_BLOCK_ENDARCRAR_ENDARC_NEXT_VOLUMERAR_ENDARC_VOLNRendarc_volnrr   RAR_FILE_SPLIT_AFTERRAR_FILE_SPLIT_BEFOREr   process_entryr   add_sizedata_offset)	r   rk   ri   r   Z	more_volsZendarcvolfileZraise_need_first_volhr#   r#   r$   rC  \  s    








zCommonParser._parse_realc                 C   s
   t  dS )z$Examine item, add into lookup cache.Nr   )r   rk   itemr#   r#   r$   rU    s    zCommonParser.process_entryc                 C   s   t dd S )N_decrypt_headerrZ  r   rk   r#   r#   r$   r\    s    zCommonParser._decrypt_headerc                 C   s   t dd S )N_parse_block_headerrZ  r]  r#   r#   r$   r^    s    z CommonParser._parse_block_headerc                 C   s   t dd S )N
_open_hackrZ  )r   r   r   r#   r#   r$   r_    s    zCommonParser._open_hackc                 C   sb   z:| j r| j jt@ s| jr0| js&W dS | |}| |W S  tjk
r\   | 	d Y dS X dS )zRead single header
        NzBroken header in RAR file)
r6  r   r9  r8  r   r\  r^  structerrorrJ  r]  r#   r#   r$   rG    s    

zCommonParser._parse_headerc                 C   s,   t |rtd| jjt@ r$t|S t|S )z3Given current vol name, construct next one
        zWorking on single FD)r   rI  r6  r   rM  _next_newvol_next_oldvol)r   rX  r#   r#   r$   rH    s
    zCommonParser._next_volnamec                 G   s$   |r|| }|| _ | jr t|d S r|   )r;  r   rv   )r   r~   argsr#   r#   r$   rJ    s
    zCommonParser._set_errorc                 C   s.  |j rT|j \}}}|ttfkr6| |}|sTtdn|tttfkrTt	|
dS |jt@ rntd|j dd}| js~d}nB| j rd}n2| rd}n$t| jrn|jtkrd}ntsd}|jtkr|jt@ dkr|j dkr| |S | r| ||S t| jr| | j||S | | j||S dS )z#Return stream object for file data.zcannot find copied filer3   z.Partial file, please start from first volume: Nr   r   )r   r?  r@  r   rv   RAR5_XREDIR_UNIX_SYMLINKRAR5_XREDIR_WINDOWS_SYMLINKr  r\   r]   encoder   rT  r{   r   r6  _must_disable_hackr   r   r   HACK_SIZE_LIMITUSE_EXTRACT_HACKr   RAR_M0r   _open_clearr_  _open_unrar_membuf_open_unrar)r   r   r   r#  r$  rA  Zuse_hackr#   r#   r$   r     sD    

 



"
zCommonParser.openc                 C   s   t r| | j|S t| |S r|   )
FORCE_TOOLrn  r   DirectReader)r   r   r#   r#   r$   rl    s    zCommonParser._open_clearc                 C   s   |j |j }t|jd}||j tdtd\}}t	|d}	zx|	
| |dkr|tkrh|t}
n
||}
|
std|j |	
|
 |t|
8 }qL|	
| |	  |  W n0 tk
r   |  |	  t|  Y nX | ||||S )Nr   .rarsuffixdirr  zread failed: )r   header_sizer_   rK  rE  header_offsetr   HACK_TMP_DIRr  fdopenra   r   r`   rv   r   rd   r   BaseExceptionunlinkrn  )r   r   r   prefixrs  sizerftmpfdtmpnametmpfrj   r#   r#   r$   _open_hack_core  s0    




zCommonParser._open_hack_corec                 C   s   t |}| j||||ddS )zIWrite in-memory archive to temp file, needed for solid archives.
        T)
force_file)membuf_tempfilern  )r   memfiler   r   r  r#   r#   r$   rm  =  s    zCommonParser._open_unrar_membufc           	      C   s@   t  }d}|r|r$|jdtjj}||||}t| |||S )zExtract using unrar
        Nr5   )
tool_setupr   replacer  r   r  open_cmdline
PipeReader)	r   r4  r   r   Ztmpfiler  setupfncmdr#   r#   r$   rn  C  s    zCommonParser._open_unrar)NNF)$r&   r'   r(   r)   r6  r8  r:  rB  rF  r;  r   r   r%   r   r   r   r   r   r   r   r   r   r   rC  rU  r\  r^  r_  rG  rH  rJ  r   rl  r  rm  rn  r#   r#   r#   r$   r/    sB   
	
e	+r/  c                   @   sh   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdZdZdd Zdd Zd	d
 Zdd ZdS )Rar3InfozRAR3 specific fields.   Nr   c                 C   sL   | j tkr,| jt@ rdS | jttB @ rHdS n| j tkrH| jttB @ rHdS dS NTF)	r   r   r   r   rT  rS  rL  r7  r9  r   r#   r#   r$   rh  j  s    


zRar3Info._must_disable_hackc                 C   s$   | j tkr |  s | jt@ tkS dS )%Returns True if entry is a directory.F)r   r   r   r   r  r   r#   r#   r$   r   u  s    zRar3Info.is_dirc                 C   s"   | j tko | jtko | jd@ dkS )#Returns True if entry is a symlink.i   i   )r   r   r   r  r   r   r#   r#   r$   r   {  s
    
zRar3Info.is_symlinkc                 C   s   | j tko|  p|   S z'Returns True if entry is a normal file.)r   r   r   r   r   r#   r#   r$   r     s    
zRar3Info.is_file)r&   r'   r(   r)   r   saltrV  
header_crcru  rv  rW  	_md_class
_md_expect
_name_sizer   r   endarc_datacrcrR  rh  r   r   r   r#   r#   r#   r$   r  V  s&   r  c                   @   sb   e Zd ZdZeZdZdd Zdd Zdd Z	d	d
 Z
dddZdd Zdd Zdd Zdd ZdS )r   zParse RAR3 file format.
    )NNNc                 C   s`   t std|d}| jd |kr8| jdd  \}}nt| j|\}}|||f| _t|||S )N*Cannot parse encrypted headers - no cryptorA   r   r   )r   r   r`   _last_aes_keyrar3_s2kr   HeaderDecrypt)r   rk   r  r    r!   r#   r#   r$   r\    s    
zRAR3Parser._decrypt_headerc           
      C   s  t  }| |_|tj}|s$dS t|tjk r@| d dS t|}|\|_	|_
|_|_|jtjkr|||jtj  }n|}| |_t||jkr| d dS tj}|jt@ rt||\|_}nd|_|j
tkr|S |j
tkr*|d7 }|jt@ r
|d7 }|}|jt@ r| ||| n|j
tkrh| |||d }|}|jt@ r| |||}n|j
tkr| |||d }|j}n|j
tkr|d7 }|}nv|j
tkr|d7 }|}n\|j
tkr|jt@ rt||\|_}|jt@ rt ||d |_!|d	7 }|j}n|j}|j
t"krD|d	d ||j }n|d	| }t#|d
@ }	|j	|	krl|S | d|j
|j	|	t| dS )"Parse common block header
        N"Unexpected EOF when reading headerr   rV   r   r@   rA   rW   r     z2Header CRC error (%02x): exp=%x got=%x (xlen = %d))$r  tellrv  r`   	S_BLK_HDRr|  rd   rJ  unpack_fromr  r   r   ru  rW  RAR_LONG_BLOCK	load_le32rV  RAR_BLOCK_MARKrL  RAR_MAIN_ENCRYPTVERRAR_MAIN_COMMENT_parse_subblocksr   _parse_file_headerRAR_FILE_COMMENTRAR_BLOCK_SUBRAR_BLOCK_OLD_AUTHRAR_BLOCK_OLD_EXTRArO  RAR_ENDARC_DATACRCr  rQ  S_SHORTrR  RAR_BLOCK_OLD_SUBr   )
r   rk   rY  rj   thdatarn   Zcrc_posZcrcdatcalc_crcr#   r#   r$   r^    s    






   zRAR3Parser._parse_block_headerc                 C   s  t ||}|t j7 }|d |_|d |_|d |_|d |_t|d |_t	|j|_
|d |_|d |_|d  |_}|d	 |_t|_|j|_|jt@ rt||\}}t||\}}| j|d
> O  _| j|d
> O  _|j|_t|||\}}|jt@ r\d|kr\|d}	|d|	 |_t|j||	d d }
|
 |_|
jr| |j|_n4|jt@ r~||_|dd|_n||_| ||_|jdd d|_|! r|jd |_|jt"@ rt|d	|\|_#}nd|_#|jt$@ rt%|||}nd |_
 |_& |_'|_(|S )z"Read file-specific header
        r   r   r   rN   r@   rO   rV   rW   rA   rC       Nr3   r  \r5   ))
S_FILE_HDRr  r|  r   r   r   r   parse_dos_timer   to_datetimer   r   r   r  r   CRC32Contextr  r  r   RAR_FILE_LARGEr  rV  
load_bytesRAR_FILE_UNICODErc   r   UnicodeFilenamedecoder   failed_decoder  r=  r   RAR_FILE_SALTr  RAR_FILE_EXTTIME_parse_ext_timer   r   r   )r   rY  r  rn   Zfld	name_sizeZh1Zh2r   nulur#   r#   r$   r    sV    











zRAR3Parser._parse_file_headerc                 C   s   |t |k rt||}|\}}}}|| }	|tj7 }|	|k r@q|tkr|tj |	krt||\}
}}}|tj7 }|||	 }t||||
||| j}| jrt	|d@ |kr| 
||_|	}q |S )z(Find old-style comment subblock
        r  )rd   r  r  r|  RAR_BLOCK_OLD_COMMENTS_COMMENT_HDRrar3_decompressr   r   r   _decode_commentr   )r   rY  r  rn   r  Z_RAR3Parser___scrcstypeZsflagsslenZpos_nextdeclenr   methcrcrm   cmtr#   r#   r$   r  6  s&    

 zRAR3Parser._parse_subblocksNc              	   C   sv   t |j}||j ||j}W 5 Q R X t|j|j||j	|j
|j||j}| jrlt|}||jkrld S | |S r|   )r_   rK  rE  rW  r`   r   r  r   r   r   r   r   r  r   r   r  )r   r   r   r}  rm   r  r  r#   r#   r$   _read_comment_v3Q  s        
zRAR3Parser._read_comment_v3c              	   C   s>   t D ]*}z||W   S  tk
r,   Y qX q|| jdS )Nr  )TRY_ENCODINGSr  UnicodeErrorr   )r   valcr#   r#   r$   r  d  s    zRAR3Parser._decodec                 C   s
   |  |S r|   )r  )r   r  r#   r#   r$   r  l  s    zRAR3Parser._decode_commentc                 C   s"  |j tkr||jt@ rnf|jt@ dkrD|| j|jd< | j	| n8t
| jdkr|| jd }|j|_|j|_| j|j7  _|j tkr|jdkr|jttB @ rnL|jt@ r| || j}t
| jdkr| jd }||_n| || j}|| _|j tkr|jt@ r|j| _|jt@ rd| _d S )Nr   r5   rZ   CMTT)r   r   r   RAR_FILE_VERSIONrT  r1  r   r=  r0  r   rd   r   r  r   r  rS  RAR_FILE_SOLIDr  r   r   rL  r  r9  r:  )r   rk   r[  oldr  r#   r#   r$   rU  o  s4    




zRAR3Parser.process_entryc                 C   s(   t tdddd d }| |||dS )Nϐ  r7   r                   )r[   r  r   r  )r   r   r   r{  r#   r#   r$   r_    s    zRAR3Parser._open_hack)N)r&   r'   r(   r)   r[   rF  r  r\  r^  r  r  r  r  r  rU  r_  r#   r#   r#   r$   r     s   YA
&r   c                   @   sH   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdZdZdZdd ZdS )Rar5Infoz$Shared fields for RAR5 records.
    rR   Nr   c                 C   s   dS )NFr#   r   r#   r#   r$   rh    s    zRar5Info._must_disable_hack)r&   r'   r(   r)   r   r  ru  rv  rW  
block_typeblock_flagsrV  block_extra_sizeZvolume_numberr  r  rh  r#   r#   r#   r$   r    s   r  c                   @   s8   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdd ZdS )Rar5BaseFilez-Shared sturct for file & service record.
    rZ   N)r   r   r   r  r  r  c                 C   s<   | j t@ rdS | jttB @ r dS | jt@ r.dS | jr8dS dS r  )r   r   r  RAR5_BLOCK_FLAG_SPLIT_BEFORERAR5_BLOCK_FLAG_SPLIT_AFTERfile_compress_flagsRAR5_COMPR_SOLIDr   r   r#   r#   r$   rh    s    

zRar5BaseFile._must_disable_hack)r&   r'   r(   r)   r   
file_flagsfile_encryptionr  r   
file_ownerfile_versionr   rh  r#   r#   r#   r$   r    s   r  c                   @   s,   e Zd ZdZeZdd Zdd Zdd ZdS )	Rar5FileInfozRAR5 file record.
    c                 C   s   | j dk	o| j d tttfkS )r  Nr   )r   re  rf  r  r   r#   r#   r$   r     s    
zRar5FileInfo.is_symlinkc                 C   s   |   p|   S r  )r   r   r   r#   r#   r$   r     s    zRar5FileInfo.is_filec                 C   s   | j s| jt@ rdS dS )r  TF)r   r  RAR5_FILE_FLAG_ISDIRr   r#   r#   r$   r     s    
zRar5FileInfo.is_dirN)	r&   r'   r(   r)   r   r   r   r   r   r#   r#   r#   r$   r    s
   r  c                   @   s   e Zd ZdZeZdS )Rar5ServiceInfozRAR5 service record.
    N)r&   r'   r(   r)   r  r   r#   r#   r#   r$   r    s   r  c                   @   s$   e Zd ZdZeZdZdZdd ZdS )Rar5MainInfozRAR5 archive main record.
    Nc                 C   s   | j t@ rdS dS r  )
main_flagsRAR5_MAIN_FLAG_SOLIDr   r#   r#   r$   rh    s    
zRar5MainInfo._must_disable_hack)	r&   r'   r(   r)   rL  r   r  rD  rh  r#   r#   r#   r$   r    s
   r  c                   @   s0   e Zd ZdZeZdZdZdZdZ	dZ
dd ZdS )Rar5EncryptionInfoz+RAR5 archive header encryption record.
    Nc                 C   s   dS )NTr#   r   r#   r#   r$   r   	  s    z!Rar5EncryptionInfo.needs_password)r&   r'   r(   r)   RAR5_BLOCK_ENCRYPTIONr   encryption_algoencryption_flagsencryption_kdf_countencryption_saltencryption_check_valuer   r#   r#   r#   r$   r    s   r  c                   @   s   e Zd ZdZeZdZdS )Rar5EndArcInfoz RAR5 end of archive record.
    N)r&   r'   r(   r)   rO  r   endarc_flagsr#   r#   r#   r$   r    s   r  c                   @   s   e Zd ZdZeZdZdZdd Zdd Z	dd	 Z
d
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ ZdS ),r   zParse RAR5 format.
    N)rZ   NNc                 C   s   | j }t|tr|dS |S )Nr3   )r   r   r   rg  r   r#   r#   r$   _get_utf8_password  s    

zRAR5Parser._get_utf8_passwordc                 C   sZ   | j d d ||fkr | j d S |dkr0td|  }td||d|> }|||f| _ |S )Nr      zToo large kdf_countr	   r   )_last_aes256_keyrv   r  r   )r   	kdf_countr  r   r    r#   r#   r$   _gen_key#  s    
zRAR5Parser._gen_keyc                 C   s8   t std| j}| |j|j}|d}t|||S )Nr  rB   )r   r   r8  r  r  r  r`   r  )r   rk   rY  r    r!   r#   r#   r$   r\  -  s    
zRAR5Parser._decrypt_headerc                 C   s  |  }d}||}t||k r0| d dS |d d@ rb|d}|sX| d dS ||7 }q0t|d\}}t||\}}|dkrdS || }	|||	t|  }
t|
|	kr| d dS |  }tt|
d	d }||kr| d
||t|
 dS t|
|\}}|tkr8| 	t
 |
\}}| ||
|}n|tkrd| 	t |
\}}| ||
|}n|tkr| 	t |
\}}| ||
|}n\|tkr| 	t |
\}}| ||
|}n0|tkr| 	t |
\}}| ||
|}nd}|r||_||_|S )r  rO   r  NrZ   rE   r   r   rY   r@   z+Header CRC error: exp=%x got=%x (xlen = %d))r  r`   rd   rJ  r  	load_vintr   
memoryviewRAR5_BLOCK_MAIN_parse_block_commonr  _parse_main_blockRAR5_BLOCK_FILEr  _parse_file_blockRAR5_BLOCK_SERVICEr  r  r  _parse_encryption_blockRAR5_BLOCK_ENDARCr  _parse_endarc_blockrv  rW  )r   rk   rv  ZpreloadZstart_bytesbr  rn   hdrlenru  r  rW  r  r  rY  r#   r#   r$   r^  5  sf    





  




zRAR5Parser._parse_block_headerc                 C   s   t |d\|_}t||\}}|| |_t||\|_}t||\|_}|jt@ rbt||\|_}|jt@ r|t||\|_	}|j	|_
|jt@ r| jtO  _|jt@ r| jtO  _||fS Nr   )r  r  r  ru  r  r  RAR5_BLOCK_FLAG_EXTRA_DATAr  RAR5_BLOCK_FLAG_DATA_AREArV  r   RAR5_BLOCK_FLAG_SKIP_IF_UNKNOWNr   RAR_SKIP_IF_UNKNOWNr  )r   rY  r  rn   r
  r#   r#   r$   r  q  s    




zRAR5Parser._parse_block_commonc                 C   s   t ||\|_}|jt@ r*t ||\|_}| jtO  _|jt@ rP| jtO  _|jt@ rh| jt	O  _|jt
@ r| jtO  _| jr| jtO  _|jt@ dkr| jtO  _|S r  )r  r  RAR5_MAIN_FLAG_HAS_VOLNRrD  r   rM  r  r7  RAR5_MAIN_FLAG_ISVOLRAR_MAIN_VOLUMERAR5_MAIN_FLAG_RECOVERYRAR_MAIN_RECOVERYr8  r9  rN  r   rY  r  rn   r#   r#   r$   r    s    



zRAR5Parser._parse_main_blockc                 C   s  t ||\|_}t ||\|_}t ||\|_}|jt@ r^t||\|_}|j d d |_|jt	@ rt
||\|_}t|_|j|_t ||\|_}t ||\|_}t||\|_}|jddd|_|jtkrt|_nt|_t|jd? d@  |_|jr@|t|d k r@t ||\}}t|||\}}| || q |j t!@ rZ| j"t#O  _"|j t$@ rt| j"t%O  _"|jt&@ r| j"t'O  _"|jt(@ r| j"t)O  _"|* r|jd |_|S )NrV   r3   r  r5   rW   r   )+r  r  r   r   RAR5_FILE_FLAG_HAS_MTIMEload_unixtimer   	timetupler   RAR5_FILE_FLAG_HAS_CRC32r  r   r  r  r  r  Zfile_host_os	load_vstrr   r  r=  r   RAR5_OS_WINDOWSr'  r   r  rk  r   r  rd   r  _process_file_extrar  r  r   rT  r  rS  r  r  r  r  r   )r   rY  r  rn   Zxsizexdatar#   r#   r$   r    sD    



zRAR5Parser._parse_file_blockc                 C   s,   t ||\|_}|jt@ r(| jtO  _|S r|   )r  r  RAR5_ENDARC_FLAG_NEXT_VOLr   rP  r  r#   r#   r$   r    s    
zRAR5Parser._parse_endarc_blockc                 C   s   t |tt krd S |d t }|td  }t| }|d t |krLd S d|> d }|  }td|||}	tt}
td }t|	D ]\}}|
||@   |N  < q|
|krt	 d S )Nr   rC   r	   )
rd   RAR5_PW_CHECK_SIZERAR5_PW_SUM_SIZEr	   digestr  r   	bytearray	enumerater   )r   check_valueZkdf_count_shiftr  Z	hdr_checkZhdr_sumZsum_hashr  r   Zpwd_hashZ	pwd_checkZlen_maskivr#   r#   r$   _check_password  s     zRAR5Parser._check_passwordc                 C   s   t ||\|_}t ||\|_}t||\|_}t|d|\|_}|jt@ r^t|d|\|_}|jt	krpt
d|jr| jr| |j|j|j || _|S )NrB      z$Unsupported header encryption cipher)r  r  r  	load_byter  r  r  RAR5_ENC_FLAG_HAS_CHECKVALr  RAR5_XENC_CIPHER_AES256rv   r   r'  r8  r  r#   r#   r$   r    s    

z"RAR5Parser._parse_encryption_blockc                 C   s   t |d\}}|tkr&| ||| n|tkr>| ||| nj|tkrV| ||| nR|tkrn| ||| n:|t	kr| 
||| n"|tkr| ||| n
|tkrn d S r  )r  RAR5_XFILE_TIME_parse_file_xtimeRAR5_XFILE_ENCRYPTION_parse_file_encryptionRAR5_XFILE_HASH_parse_file_hashRAR5_XFILE_VERSION_parse_file_versionRAR5_XFILE_REDIR_parse_file_redirRAR5_XFILE_OWNER_parse_file_ownerRAR5_XFILE_SERVICE)r   rY  r  Zxtypern   r#   r#   r$   r    s     zRAR5Parser._process_file_extrac                 C   s   t ||\}}t}|t@ rt}|t@ rJ|||\|_}|j d d |_|t@ rb|||\|_	}|t
@ rz|||\|_}|t@ r|t@ rt||\}}t|j||_|t@ rt||\}}t|j	||_	|t
@ rt||\}}t|j||_d S )NrV   )r  load_windowstimeRAR5_XTIME_UNIXTIMEr  RAR5_XTIME_HAS_MTIMEr   r  r   RAR5_XTIME_HAS_CTIMEr   RAR5_XTIME_HAS_ATIMEr   RAR5_XTIME_UNIXTIME_NSr  to_nsdatetime)r   rY  r  rn   ZtflagsZldrnsecr#   r#   r$   r-    s*    zRAR5Parser._parse_file_xtimec           
      C   s   t ||\}}t ||\}}t||\}}t|d|\}}t|d|\}}d }	|t@ rft|d|\}	}|t@ rzd |_t|_||||||	f|_| j	t
O  _	d S )NrB   r(  )r  r)  r  RAR5_XENC_CHECKVALRAR5_XENC_TWEAKEDr  NoHashContextr  r  r   r   )
r   rY  r  rn   algor   r  r  r!   Zcheckvalr#   r#   r$   r/    s    z!RAR5Parser._parse_file_encryptionc                 C   sL   t ||\}}|tkrHt|d|\|_}|jd t@ dkrHt|_|j|_d S )NrC   r   r   )	r  RAR5_XHASH_BLAKE2SPr  r   r  rB  Blake2SPr  r  )r   rY  r  rn   Z	hash_typer#   r#   r$   r1  .  s    zRAR5Parser._parse_file_hashc                 C   s*   t ||\}}t ||\}}||f|_d S r|   )r  r  )r   rY  r  rn   r   versionr#   r#   r$   r3  6  s    zRAR5Parser._parse_file_versionc                 C   sF   t ||\}}t ||\}}t||\}}|dd}|||f|_d S )Nr3   r  )r  r  r  r   )r   rY  r  rn   r#  r$  rA  r#   r#   r$   r5  ;  s
    zRAR5Parser._parse_file_redirc           	      C   s   d  } } }}t ||\}}|t@ r4t||\}}|t@ rJt||\}}|t@ r`t ||\}}|t@ rvt ||\}}||||f|_d S r|   )r  RAR5_XOWNER_UNAMEr  RAR5_XOWNER_GNAMERAR5_XOWNER_UIDRAR5_XOWNER_GIDr  )	r   rY  r  rn   Z	user_name
group_nameZuser_idZgroup_idr   r#   r#   r$   r7  B  s    zRAR5Parser._parse_file_ownerc                 C   s   |j tkr|jrq|jt@ dkr@|| j|jd< | j	| qt
| jdkr| jd }|j|_|j|_|j|_| j|j7  _n |j tkr|jdkr| || d S )Nr   r5   rZ   r  )r  r  r  r  r  r1  r   r=  r0  r   rd   r   r  r   r   r  _load_comment)r   rk   r[  r  r#   r#   r$   rU  Q  s    



zRAR5Parser.process_entryc              	   C   s   |j ttB @ rd S |jtkr d S |jt@ rn|j\}}}}}}|tkrHd S | 	||}	t
||	|}
|
|j}n| |}| }W 5 Q R X |ddd }|d| _d S )Nr  r   r   r3   )r  r  r  r   rk  r   r   r  r+  r  r  r`   r   rl  splitr  r   )r   rk   r[  rD  Z_RAR5Parser___flagsr  r  r!   Z_RAR5Parser___checkvalr    r   r  Z	cmtstreamr#   r#   r$   rM  d  s     

zRAR5Parser._load_commentc                 C   s@   d}d}t t|| }t t|| }| ||t| |S )Ns     s     )S_LONGr   r   r  rf   )r   r   r   Zmain_hdrZ
endarc_hdrr#   r#   r$   r_  {  s
    zRAR5Parser._open_hack)r&   r'   r(   r)   rf   rF  r8  r  r  r  r\  r^  r  r  r  r  r'  r  r  r-  r/  r1  r3  r5  r7  rU  rM  r_  r#   r#   r#   r$   r     s0   
<-r   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )r  z0Handle RAR3 unicode filename decompression.
    c                 C   s2   t || _t || _d | _| _t  | _d| _d S r  )r"  std_nameencdatarn   encposrj   r  )r   r   rQ  r#   r#   r$   r%     s
    

zUnicodeFilename.__init__c                 C   sB   z | j | j }|  jd7  _|W S  tk
r<   d| _Y dS X dS )zCopy encoded byte.r   r   N)rQ  rR  
IndexErrorr  )r   r  r#   r#   r$   enc_byte  s    zUnicodeFilename.enc_bytec                 C   s6   z| j | j W S  tk
r0   d| _td Y S X dS )z$Copy byte from 8-bit representation.r   ?N)rP  rn   rS  r  ordr   r#   r#   r$   std_byte  s
    zUnicodeFilename.std_bytec                 C   s*   | j | | j | |  jd7  _dS )zCopy 16-bit value to result.r   N)rj   r   rn   )r   lohir#   r#   r$   put  s    zUnicodeFilename.putc           	      C   s  |   }d}| jt| jk r|dkr2|   }d}|d8 }||? d@ }|dkr`| |   d q|dkrz| |   | q|dkr| |   |    q|   }|d@ r|   }t|d@ d D ] }|  | d@ }| || qqt|d D ]}| |  d qq| jd	d
S )z"Decompress compressed UTF16 value.r   rA   r   rN   r   rE         r4   r  )	rT  rR  rd   rQ  rZ  rangerW  rj   r  )	r   rY  Zflagbitsr   r  nr  _rX  r#   r#   r$   r    s.    zUnicodeFilename.decodeN)	r&   r'   r(   r)   r%   rT  rW  rZ  r  r#   r#   r#   r$   r    s   
r  c                       s   e Zd ZdZdZdZdZdZdZdZ	dZ
dZdZdd Zd#d	d
Zdd Zdd Z fddZdd Zdd Zdd Zd$ddZdd Zdd Zdd Zdd  Zd!d" Z  ZS )%r/   a  Base class for file-like object that :meth:`RarFile.open` returns.

    Provides public methods and common crc checking.

    Behaviour:
     - no short reads - .read() and .readinfo() read as much as requested.
     - no internal buffer, use io.BufferedReader for that.
    Nrbr   Fc                 C   sX   |j | _|| _|| _| jr$| j  | jr0t}n| jjp:t}| | _	d | _| jj
| _d S r|   )r   r   _parser_infrB  r   _seekingrC  r  _md_contextr   _remain)r   parserr   Zmd_classr#   r#   r$   _open_extfile  s    
zRarExtFile._open_extfilerZ   c                 C   s   |dks|dk r| j }n|| j kr(| j }|dkr4dS g }|}|dkr| |}|sTq|| | j| |  j t|8  _ |t|8 }q<d|}|dkrtd|t|f |r| j dkr|   |S )z8Read all or specified amount of data from archive entry.Nr   r  z*Failed the read enough data: req=%d got=%d)	re  _readr   rd  r   rd   r	  rv   _check)r   r^  rj   origrm   r#   r#   r$   r`     s,    



zRarExtFile.readc                 C   sx   | j  }| jj}|dkrdS |dkr*dS | jrDt| jdt   | jdkrVt	d||krtt	d| jj
||f dS )zCheck final CRC.N r   zFailed the read enough dataz3Corrupt file - CRC check failed: %s - exp=%r got=%r)rd  r!  rb  r  _returncodecheck_returncoder  
get_errmapre  rv   r   )r   finalexpr#   r#   r$   ri  		  s     

  zRarExtFile._checkc                 C   s   t ddS )z$Actual read that gets sanitized cnt.rh  NrZ  r   cntr#   r#   r$   rh  	  s    zRarExtFile._readc                    s$   t    | jr | j  d| _dS zClose open resources.N)r}   r   rB  r   r   r#   r$   r   	  s    

zRarExtFile.closec                 C   s   |    dS )z-Hook delete to make sure tempfile is removed.Nr   r   r#   r#   r$   __del__&	  s    zRarExtFile.__del__c                 C   s   t ddS )zJZero-copy read directly into buffer.

        Returns bytes read.
        readintoNrZ  r   rj   r#   r#   r$   ru  *	  s    zRarExtFile.readintoc                 C   s   | j j| j S )z5Return current reading position in uncompressed data.)rb  r   re  r   r#   r#   r$   r  1	  s    zRarExtFile.tellc                 C   s   | j st | _d| _ | jj}|  }|dkr2|}n,|dkrD|| }n|dkrV|| }ntd|dk rld}n||krx|}||kr| ||  n| | j	| j | | |  S )a  Seek in data.

        On uncompressed files, the seeking works by actual
        seeks so it's fast.  On compressed files its slow
        - forward seeking happens by reading ahead,
        backwards by re-opening and decompressing from the start.
        Tr   r   r   zInvalid value for whence)
rc  rC  rd  rb  r   r  r   _skiprg  ra  )r   offsetwhencefsizeZcur_ofsZnew_ofsr#   r#   r$   rE  5	  s*    



zRarExtFile.seekc                 C   s   t | |t dS )zRead and discard dataN)r   r   rq  r#   r#   r$   rw  ^	  s    zRarExtFile._skipc                 C   s   dS )zReturns TrueTr#   r   r#   r#   r$   readableb	  s    zRarExtFile.readablec                 C   s   dS )z:Returns False.

        Writing is not supported.
        Fr#   r   r#   r#   r$   writablef	  s    zRarExtFile.writablec                 C   s   dS )z]Returns True.

        Seeking is supported, although it's slow on compressed files.
        Tr#   r   r#   r#   r$   seekablem	  s    zRarExtFile.seekablec                 C   s   |   S )zRead all remaining data)r`   r   r#   r#   r$   readallt	  s    zRarExtFile.readall)rZ   )r   )r&   r'   r(   r)   r   r   ra  rb  rB  re  rl  rd  rc  rg  r`   ri  rh  r   rt  ru  r  rE  rw  r{  r|  r}  r~  r   r#   r#   r   r$   r/     s0   
 	
)c                       sR   e Zd ZdZd fdd	Zdd Z fddZd	d
 Z fddZdd Z	  Z
S )r  z-Read data from pipe, handle tempfile cleanup.Nc                    s,   t    || _d | _|| _| || d S r|   )r}   r%   _cmd_proc	_tempfilerg  )r   rf  r   r  tempfiler   r#   r$   r%   }	  s
    
zPipeReader.__init__c                 C   sP   | j s
d S | j j| j j| j jfD ]}|r |  q | j   | j j| _d | _ d S r|   )r  r   stderrstdinr   wait
returncoderl  )r   r   r#   r#   r$   _close_proc	  s    


zPipeReader._close_procc                    s6   t  || |   d| _t| j| _| jj| _d S r  )	r}   rg  r  rl  custom_popenr  r  r   rB  r   rf  r   r   r#   r$   rg  	  s
    zPipeReader._open_extfilec                 C   sn   | j |}t||ks|s |S |g}|t|8 }|dkrd| j |}|sLqd|t|8 }|| q2d|S )zRead from pipe.r   r  )rB  r`   rd   r   r	  )r   rr  rm   rj   r#   r#   r$   rh  	  s    zPipeReader._readc                    sH   |    t   | jrDzt| j W n tk
r<   Y nX d| _dS rs  )r  r}   r   r  r  rz  rr   r   r   r#   r$   r   	  s    
zPipeReader.closec                 C   s~   t |}|| jkr| j}t|}d }}||k rz| j||| }|sJqz| j||||   |  j|8  _||7 }q(|S z$Zero-copy read directly into buffer.r   )rd   re  r  rB  ru  rd  r   )r   rj   rr  vbufresgotr#   r#   r$   ru  	  s    

zPipeReader.readinto)N)r&   r'   r(   r)   r%   r  rg  rh  r   ru  r   r#   r#   r   r$   r  z	  s   
r  c                       sX   e Zd ZdZdZdZdZ fddZ fddZdd Z	d	d
 Z
dd Zdd Z  ZS )rp  z2Read uncompressed data directly from archive.
    Nc                    s   t    | || d S r|   )r}   r%   rg  r  r   r#   r$   r%   	  s    
zDirectReader.__init__c                    sV   t  || | jj| _t| jd| _| j| jjd | j	
| j| _| jj| _d S r  )r}   rg  rb  rK  _volfiler_   rB  rE  rv  ra  rG  _currV  
_cur_availr  r   r#   r$   rg  	  s    
zDirectReader._open_extfilec                 C   s|   |dkrx| j dkr|  sqx|| j krH|| j 8 }|  j| j 8  _d| _ q | j|d |  j |8  _ |  j|8  _d}q dS )zHRAR Seek, skipping through rar files to get to correct position
        r   r   N)r  
_open_nextre  rB  rE  rq  r#   r#   r$   rw  	  s    


zDirectReader._skipc                 C   s   | j  }| jj| jj | j }||kr6| j |d g }|dkr| jdkrV|  sVq|| jkrp| j | j}n| j |}|sq|t	|8 }|  jt	|8  _|
| q:t	|dkr|d S d|S )z+Read from potentially multi-volume archive.r   r   r  )rB  r  r  rW  rV  r  rE  r  r`   rd   r   r	  )r   rr  rn   needrj   rm   r#   r#   r$   rh  	  s(    


zDirectReader._readc                 C   s   | j jt@ dkrdS | jr*| j  d| _| j| j| _t| jdd}|| _|	t
| jj}|| jjkrttd| j|}|std|jttfkr|jrt||jd qt|j| jjkrtd|| _ |j| _d	S )
zProceed to next volume.r   FNr`  zInvalid signaturezUnexpected EOFr   zDid not found file entryT)r  r   rS  rB  r   ra  rH  r  r   r`   rd   rF  rv   rG  r   r  rL  rV  rE  r   rb  r  )r   rk   ri   curr#   r#   r$   r  
  s.    
zDirectReader._open_nextc                 C   s   d}t |}|t|k r| jdkr,|  s,qt|| }|| jkrH| j}| j||||  }|sfq| j||||   |  j|8  _|  j|8  _||7 }q|S r  )	r  rd   r  r  rB  ru  rd  r   re  )r   rj   r  r  rr  r  r#   r#   r$   ru  5
  s"    


zDirectReader.readinto)r&   r'   r(   r)   r  r  r  r%   rg  rw  rh  r  ru  r   r#   r#   r   r$   rp  	  s   	 "rp  c                   @   s*   e Zd ZdZdd Zdd Zd	ddZdS )
r  z0File-like object that decrypts from another filec                 C   s   || _ t||| _d| _d S )Nr  )r   r   r"   rj   )r   r   r    r!   r#   r#   r$   r%   Q
  s    zHeaderDecrypt.__init__c                 C   s
   | j  S )z2Current file pos - works only on block boundaries.)r   r  r   r#   r#   r$   r  V
  s    zHeaderDecrypt.tellNc                 C   s   |dkrt d|t| jkr@| jd| }| j|d | _|S | j}d| _|t|8 }d}|dkr| j|}t||k r~q| j|}|t|kr||7 }|t|8 }q\||d| 7 }||d | _d}q\|S )zRead and decrypt.rL   z-Bad count to header decrypt - wrong password?Nr  rB   r   )rv   rd   rj   r   r`   r"   r   )r   rr  r  blklenencdecr#   r#   r$   r`   Z
  s,    zHeaderDecrypt.read)N)r&   r'   r(   r)   r%   r  r`   r#   r#   r#   r$   r  O
  s   r  c                   @   sZ   e Zd ZdZdZdddZdddZd	d
 ZdddZdd Z	dd Z
dd Zdd ZdS )r_   z*Input may be filename or file object.
    )rB  _need_closerK   c                 C   s:   t |r"d| _|| _| jd nd| _t|d|| _d S )NFr   Tr`  )r   r  rB  rE  r   )r   rh   bufsizer#   r#   r$   r%   
  s    zXFile.__init__Nc                 C   s   | j |S )zRead from file.)rB  r`   )r   r^  r#   r#   r$   r`   
  s    z
XFile.readc                 C   s
   | j  S )zReturn file pos.)rB  r  r   r#   r#   r$   r  
  s    z
XFile.tellr   c                 C   s   | j ||S )zMove file pos.)rB  rE  )r   ofsry  r#   r#   r$   rE  
  s    z
XFile.seekc                 C   s   | j |S )zRead into buffer.)rB  ru  rv  r#   r#   r$   ru  
  s    zXFile.readintoc                 C   s   | j r| j  dS )zClose file object.N)r  rB  r   r   r#   r#   r$   r   
  s    zXFile.closec                 C   s   | S r|   r#   r   r#   r#   r$   r   
  s    zXFile.__enter__c                 C   s   |    d S r|   r   )r   r   r  tbr#   r#   r$   r   
  s    zXFile.__exit__)rK   )N)r   )r&   r'   r(   r)   	__slots__r%   r`   r  rE  ru  r   r   r   r#   r#   r#   r$   r_   z
  s   
	

r_   c                   @   s2   e Zd ZdZdddZdd Zdd Zd	d
 ZdS )rC  zNo-op hash function.Nc                 C   s   dS )Z
InitializeNr#   r   rm   r#   r#   r$   r%   
  s    zNoHashContext.__init__c                 C   s   dS )zUpdate dataNr#   r  r#   r#   r$   r   
  s    zNoHashContext.updatec                 C   s   dS )z
Final hashNr#   r   r#   r#   r$   r!  
  s    zNoHashContext.digestc                 C   s   dS )Hexadecimal digest.Nr#   r   r#   r#   r$   	hexdigest
  s    zNoHashContext.hexdigest)N)r&   r'   r(   r)   r%   r   r!  r  r#   r#   r#   r$   rC  
  s
   
rC  c                   @   s8   e Zd ZdZdgZdddZdd Zdd	 Zd
d ZdS )r  zHash context that uses CRC32._crcNc                 C   s   d| _ |r| | d S r  )r  r   r  r#   r#   r$   r%   
  s    zCRC32Context.__init__c                 C   s   t || j| _dS )zProcess data.N)r   r  r  r#   r#   r$   r   
  s    zCRC32Context.updatec                 C   s   | j S )zFinal hash.)r  r   r#   r#   r$   r!  
  s    zCRC32Context.digestc                 C   s   d|    S )r  z%08x)r!  r   r#   r#   r$   r  
  s    zCRC32Context.hexdigest)N)	r&   r'   r(   r)   r  r%   r   r!  r  r#   r#   r#   r$   r  
  s   
r  c                   @   sZ   e Zd ZdZddddgZdZdZdZdd
dZdd Z	dd Z
dd Zdd Zdd Zd	S )rF  zBlake2sp hash context.
    _thread_bufr  _digestrC   rD   rA   Nc                 C   s^   d| _ d| _d | _g | _t| jD ](}| |d|| jd k}| j| q"|rZ| | d S )Nr  r   r   )	r  r  r  r  r]  parallelism_blake2sr   r   )r   rm   r%  ctxr#   r#   r$   r%   
  s    zBlake2SP.__init__c                 C   s   t |||dd| jdS )Nr   rC   )Znode_offsetZ
node_depthZ	last_nodedepthZ
inner_sizeZfanout)r   r  )r   r  r  Zis_lastr#   r#   r$   r  
  s
      zBlake2SP._blake2sc                 C   s(   | j | j | | jd | j | _d S )Nr   )r  r  r   r  )r   Zblkr#   r#   r$   
_add_block
  s    zBlake2SP._add_blockc                 C   s   t |}| j}| jrl|t| j }t||k rD|  j| 7  _dS | | j|d|    ||d }t||kr| |d|  ||d }ql| | _dS )zHash data.
        N)r  
block_sizer  rd   tobytesr  )r   rm   viewbsr  r#   r#   r$   r   
  s    zBlake2SP.updatec                 C   sZ   | j dkrT| jr"| | j d| _| ddd}| jD ]}||  q6| | _ | j S )z#Return final digest value.
        Nr  r   r   T)r  r  r  r  r  r   r!  )r   r  r  r#   r#   r$   r!  
  s    


zBlake2SP.digestc                 C   s   t |  dS )r  ascii)r   r!  r  r   r#   r#   r$   r    s    zBlake2SP.hexdigest)N)r&   r'   r(   r)   r  digest_sizer  r  r%   r  r  r   r!  r  r#   r#   r#   r$   rF  
  s   
rF  c                   @   sZ   e Zd ZdZdZdZedZedZ	dZ
dd	d
Zdd Zdd Zdd Zdd ZdS )Rar3Sha1z"Emulate buggy SHA1 from RAR3.
       rD   s   >16Ls   <16L)_nbytes_md_rarbugr  Fc                 C   s"   t  | _d| _|| _| | d S r  )r   r  r  r  r   )r   rm   rarbugr#   r#   r$   r%     s    zRar3Sha1.__init__c                 C   sr   | j | | jd@ }|  jt|7  _| jrnt|dkrn| j| }|| j t|krn| || || j7 }qDdS )zProcess more data.?   rD   N)r  r   r  rd   r  r  _corrupt)r   rm   Zbufposdposr#   r#   r$   r     s    

zRar3Sha1.updatec                 C   s
   | j  S )zReturn final state.)r  r!  r   r#   r#   r$   r!  #  s    zRar3Sha1.digestc                 C   s
   | j  S )z!Return final state as hex string.)r  r  r   r#   r#   r$   r  '  s    zRar3Sha1.hexdigestc                 C   s   t | j||}tddD ]`}||d d@  ||d d@  A ||d d@  A ||d d@  A }|d> |d? B d	@ ||d@ < q| jj||f|  d
S )zCorruption from SHA1 core.rB   P   rN   r  rA      r      l    N)list_BLK_BEr  r]  _BLK_LE	pack_into)r   rm   r  wsr  tmpr#   r#   r$   r  +  s
    @zRar3Sha1._corruptN)r  F)r&   r'   r(   r)   r  r  r`  r   r  r  r  r%   r   r!  r  r  r#   r#   r#   r$   r    s   


r  z<Lz<Hz<Bz<HBHHz
<LLBLLBBHLz<HBBHc                 C   sh   t |d t| }d }}||k r\| | }||d@ |> 7 }|d7 }|d7 }|dk r||fS qtddS )	zLoad RAR5 variable-size int.   r   r[  r   rW   rE   zcannot load vintN)minrd   rv   )rj   rn   limitr  r  r	  r#   r#   r$   r  A  s    
r  c                 C   s0   |d }|t | krtdt| |d |fS )zLoad single byter   zcannot load byter   )rd   rv   S_BYTEr  rj   rn   endr#   r#   r$   r)  O  s    r)  c                 C   s0   |d }|t | krtdt| |d |fS )z!Load little-endian 32-bit integerr@   zcannot load le32r   )rd   rv   rO  r  r  r#   r#   r$   r  W  s    r  c                 C   s,   || }|t | krtd| || |fS )zLoad sequence of byteszcannot load bytes)rd   rv   )rj   numrn   r  r#   r#   r$   r  _  s    r  c                 C   s   t | |\}}t| ||S )z"Load bytes prefixed by vint length)r  r  )rj   rn   r  r#   r#   r$   r  g  s    r  c                 C   s"   t | |\}}t|}t||fS )zLoad LE32 dos timestamp)r  r  r  )rj   rn   stamptupr#   r#   r$   load_dostimem  s    r  c                 C   s$   t | |\}}t|tj}||fS )zLoad LE32 unix timestamp)r  r   fromtimestampr   utc)rj   rn   secsdtr#   r#   r$   r  t  s    r  c                 C   s^   d}t | |\}}t | |\}}t|d> |B d\}}t|| tj}t||d }||fS )zLoad LE64 windows timestampl    !l
 rC   i d   )r  divmodr   r  r   r  r?  )rj   rn   Z
unix_epochZval1Zval2r  Zn1secsr  r#   r#   r$   r9  {  s    r9  z^[0-9]+$c                 C   s   t j| \}}| dkr$|d } t| d }|dkr~d| |   krPdkr`n nt| |dS | | dt jfkrtq~|d8 }q0td	|  d
S )zNew-style next volume
    rk  z.exez.sfxrq  r   r   09Fr5   zCannot construct volume name: N)r  r   splitextlowerrd   _inc_volnamer  rx   )rX  r   extr%  r#   r#   r$   rb    s    
rb  c                 C   sd   t j| \}}| dkr d}|dd }t|rLt|t|d d}n|dd d }|| S )zOld-style next volume
    r  rq  r   Nr   TZ00)r  r   r  r  _rc_nummatchr  rd   )rX  r   r  Zsfxr#   r#   r$   rc    s    
rc  c                 C   s   t | }|dkr|| dkrBd||< |d8 }|dk r|dd qd||   krZdk s`n |r|tt|| d ||< qq||d d qqd|S )z>increase digits with carry, otherwise just increment char
    r   r  r  r   1rk  )r  insertchrrV  r	  )rX  r%  Z	inc_charsr  r#   r#   r$   r    s    r  c                 C   s   d}|d t |kr,t||d }|d7 }t|d? ||| j\}}t|d? ||\| _}t|d? ||\| _}t|d? ||\| _}|r|| _| dd | _	|S )z(Parse all RAR3 extended time fields
    r   r   r(  rA   r@   NrV   )
rd   r  r  _parse_xtimer   r   r   r   r  r   )rY  rm   rn   r   r   r#   r#   r$   r    s    r  c           	      C   s   d}| d@ r|st ||\}}d}| d@ }t|D ]"}t||\}}|d> |d? B }q2| d@ rz|jdk rz|j|jd d	}t||d
 }||fS )z'Parse one RAR3 extended time field
    NrA   r   rN   rB   r@   ;   r   )secondr  )r  r]  r)  r  r  r?  )	flagrm   rn   Zbasetimer  remrr  r_  r	  r#   r#   r$   r    s    r  c                 C   s@   t | tttfrdS d}dD ]}|o,t| |}q|s<tddS )zFilename or file object?
    FT)r`   r  rE  zInvalid object passed as file)r   bytesr   r
   hasattrr   )objr  ar#   r#   r$   r     s    r   c           
      C   s   t | ts| d} t| d| }tdd}d}tdD ]\}tdD ]N}t|d | }|	| |	|dd	  |d
krH||
 dd 7 }qHq<|
 dd }tdtd| }	|	|fS )z!String-to-key hash for RAR3.
    r3   r4   T)r  r  rB   rM   NrN   r      r  <LLLLz>LLLL)r  )r   r   r  r"  rg  r  r]  rO  r   r   r!  r   )
r   r  seedrY  r!   r%  jrr  Zkey_beZkey_ler#   r#   r$   r    s    



r  c                 C   sb  |t kr|t@ dkr|S |ttB tB @ }|tO }d}d}	t}
tt||t	||	| |t||
	}||7 }|rr||7 }t
jt| }t
dt||| }t|dd d@ }t
|t||| }t
dtddd	 }t }td
td\}}t|d}zV|t| | |  |  |t@ r"|p$d}|||}t|}| d W S |  t| X dS )zdDecompress blob of compressed data.

    Used for data with non-standard header - eg. comments.
    r   s   datai  =r   Nr  r  r  r  rq  rr  r  )rk  r   r  RAR_FILE_DICTMASKr  DOS_MODE_ARCHIVEr  r   rd   r(  r  r|  r   r   rL  r  r   rw  r  rx  r   rz  ra   r[   r  r  communicate)versr  rm   r  r   r  r   r  r  dater   ZfhdrZhlenhdrZhcrcmhr  r~  r  r  Zcurpwdr  pr#   r#   r$   r    sD        r  c                 C   s   |r.t | dkr(| d dkr(| dd } t}nt}|| rH|d| } g }| dD ]8}|dkrdqV|r|d d	kr|dd d }|| qV||S )
z)Make filename safe for write access.
    r   :r   Nr_  r5   )rk  r   z..rZ   ) r   )rd   RC_BAD_CHARS_WIN32RC_BAD_CHARS_UNIXsearchsubrN  r   r	  )r  pathsepZis_win32rcpartssegr#   r#   r$   r  =  s    
r  c                 C   sD   |dkr@||kr|  |}n
|  |}|s2td|t|8 }q dS )z(Read and drop fixed amount of data.
    r   zcannot load dataN)r`   rv   rd   )r  r|  r  r  r#   r#   r$   r   S  s    
r   c                 C   s   | \}}}}}}zt ||||||W S  tk
r8   Y nX d}tdt|d}tdt||| }t|d}t|d}t|d}t ||||||S )z4Convert 6-part time tuple into datetime object.
    )r   r     r     r  r  r  r  r  r  r  r  r   r(     r  )r   r   maxr  )r  yearmondayrY  r   smdayr#   r#   r$   r  `  s    


r  c                 C   sz   | d@ | d?  }} | d@ | d?  }} | d@ | d?  }} | d@ | d?  }} | d@ | d?  }} | d@ d }||||||d	 fS )
z)Parse standard 32-bit DOS timestamp.
    r  rO   r  rV   r  r@   r[  i  r   r#   )r  secZmnhrr  r   yrr#   r#   r$   r  v  s    r  c                       s   e Zd ZU dZdZeed< dddd fddZd  fdd	Zd! fdd	Z	d"dddddZ
 fddZ fddZ fddZdd Zdd Zdd Zdd Z  ZS )#
nsdatetimeztDatetime that carries nanoseconds.

    Arithmetic operations will lose nanoseconds.

    .. versionadded:: 4.0
    )
nanosecondr  Nr   )foldr  c	                   sf   |
rt |
dn|df\}}|dkr<t|||||||||	d	S t j| |||||||||	d
}|
|_|S )N  r   )r	  )r  r   r}   __new__r  )clsr  monthr  hourminuter  microsecondtzinfor	  r  Zusecmodr   r   r#   r$   r    s     znsdatetime.__new__Tautoc                    sN   |dkr@t  |ddd\}}| d| jd|dd  S t  ||S )z6Formats with nanosecond precision by default.
        r  microsecondsr   r   Z09drV   N)r}   	isoformatrN  r  )r   r  Ztimespecprepostr   r#   r$   r    s    znsdatetime.isoformatc                    s:   t  |}| j|j|j|j|j|j|j| j	|j
|jd	S )z!Convert to new timezone.
        r  r  r	  )r}   
astimezoner   r  r  r  r  r  r  r  r  r	  )r   tzr  r   r#   r$   r    s      znsdatetime.astimezonec	                C   s   | j |dkr| jn||dkr"| jn||dkr2| jn||dkrB| jn||dkrR| jn||dkrb| jn||
dkr|dkrz| jq|d n|
|dkr| jn||	dkr| j	n|	d	S )z=Return new timestamp with specified fields replaced.
        Nr
  r  )
r   r  r  r  r  r  r  r  r  r	  )r   r  r  r  r  r  r  r  r  r	  r  r#   r#   r$   r    s    znsdatetime.replacec                    s$   | j rtt  | j fS t  S r|   )r  hashr}   __hash__r   r   r#   r$   r    s    znsdatetime.__hash__c                    s,   t  |o*| jt|tr |jn|jd kS Nr
  )r}   __eq__r  r   r  r  r   otherr   r#   r$   r    s    znsdatetime.__eq__c                    s8   t  |p6t  |o6| jt|tr,|jn|jd kS r  )r}   __gt__r  r  r   r  r  r   r   r#   r$   r"    s    znsdatetime.__gt__c                 C   s   | |kp| |k S r|   r#   r   r#   r#   r$   __lt__  s    znsdatetime.__lt__c                 C   s
   | |k  S r|   r#   r   r#   r#   r$   __ge__  s    znsdatetime.__ge__c                 C   s
   | |k S r|   r#   r   r#   r#   r$   __le__  s    znsdatetime.__le__c                 C   s
   | |k S r|   r#   r   r#   r#   r$   __ne__  s    znsdatetime.__ne__)NNr   r   r   r   N)r  r  )N)NNNNNNNN)r&   r'   r(   r)   r  int__annotations__r  r  r  r  r  r  r"  r#  r$  r%  r&  r   r#   r#   r   r$   r    s4   
     	     r  c                 C   s2   |s| S t | j| j| j| j| j| j| j| j|d	S )z#Apply nanoseconds to datetime.
    )r  r	  r  )	r  r  r  r  r  r  r  r  r	  )r  r@  r#   r#   r$   r?    s      r?  c                 C   s2   t |  }t| tr| jn| jd }|d | S )z.Convert datatime instance to nanoseconds.
    r
  i ʚ;)r'  	timestampr   r  r  r  )r  r  Znsecsr#   r#   r$   r,    s    r,  c              
   C   s   t rdnd}zt| dttt|d}W n\ tk
r } z>|jtjkrLtdd|jtj	ksd|jtj
krntdd W 5 d}~X Y nX |S )z;Disconnect cmd from parent fds, read only from stdout.
    i   r   )r  r   r  r  creationflagszUnrar not installed?NzCannot execute unrar)r  r   r   r   r   rr   errnoENOENTr   EACCESEPERM)r  r*  r  exr#   r#   r$   r    s    


r  c                 C   sz   | dkrdS | dkr*| t |k r*||  }n | dkr8t}n| dk rFt}nt}|r`d|j| |f }nd|j| f }||dS )z2Raise exception according to unrar exit code.
    r   Nr\  z%s [%d]: %sz%s [%d])rd   r   r   r   r)   )codeouterrmapexcr~   r#   r#   r$   rm    s    
rm  c                 C   sp   |  dd tdtd\}}t|d}zt| |t |  W n( t	k
rj   |  t
|  Y nX |S )z.Write in-memory file object to real file.
    r   rq  rr  r  )rE  r   rw  r  rx  r  r  r   r   ry  rz  )r  r~  r  r  r#   r#   r$   r    s    
r  c                   @   sH   e Zd Zdd Zdd ZdddZdd	 ZdddZdd Zdd Z	dS )	ToolSetupc                 C   s
   || _ d S r|   r  )r   r  r#   r#   r$   r%     s    zToolSetup.__init__c                 C   sH   |  dd }z t|}| \}}|jdkW S  tk
rB   Y dS X d S )N	check_cmdr   F)get_cmdliner  r  r  r   )r   cmdliner  r1  r_  r#   r#   r$   check   s    zToolSetup.checkNc                 C   s*   |  d|}|| |r&| || |S )Nopen_cmd)r7  r   add_file_arg)r   r   ZrarfnZfilefnr8  r#   r#   r$   r  )  s
    
zToolSetup.open_cmdlinec                 C   s
   | j d S )Nr2  r5  r   r#   r#   r$   rn  0  s    zToolSetup.get_errmapFc                 C   sJ   t | j| }t |d  |d< |dkr,|S | || |sF|d |S )Nr   r6  z--)r  r  globalsadd_password_argr   )r   r    r   Znodashr8  r#   r#   r$   r7  3  s    
zToolSetup.get_cmdlinec                 C   s   | | d S r|   )r   )r   r8  r   r#   r#   r$   r;  =  s    zToolSetup.add_file_argc                 C   s   |dk	r|t |ts|d}| jd }|dkrL| jd d }t| dqt |trf|||  q|| || n|| jd  dS )z/Append password switch to commandline.
        Nr3   r5  r:  r   z does not support passwordsno_password)r   r   r  r  r   r   extend)r   r8  r   rd  Ztoolr#   r#   r$   r=  @  s    




zToolSetup.add_password_arg)N)F)
r&   r'   r(   r%   r9  r  rn  r7  r;  r=  r#   r#   r#   r$   r4    s   	


r4  )
UNRAR_TOOLr  -inul)r@  rA  z-?-p)z-p-)r:  r6  r5  r>  r2  )	UNAR_TOOLz-qz-o-)rC  z-version)rB  )rB  rk  )BSDTAR_TOOLz-xz--to-stdoutz-f)rE  z	--versionr#   )SEVENZIP_TOOLe-so-bb0)rF  r%  )SEVENZIP2_TOOLrG  rH  rI  )rJ  r%  Tc           	      C   s   |rda t dk	rt S g }| r&|t |r4|t |rB|t |rP|t |r^|t |D ]}t|}| rb|a  qqbt dkrt	dt S )z*Pick a tool, return cached ToolSetup.
    NzCannot find working tool)
CURRENT_SETUPr   UNRAR_CONFIGUNAR_CONFIGSEVENZIP_CONFIGSEVENZIP2_CONFIGBSDTAR_CONFIGr4  r9  r   )	r0   r1   r2   ZsevenzipZ	sevenzip2forcelstZconfr  r#   r#   r$   r    s.    




r  c              	   C   s   ddl }|jtjd}|jdd}|jdddd	d
 |jdddddd |jddddd
 || }|jrt|j}|	  W 5 Q R X nV|j
rt|j
}|  W 5 Q R X n0|jrt|jd }||jd  W 5 Q R X dS )z7Minimal command-line interface for rarfile module.
    r   N)descriptionT)requiredz-lz--list	<rarfile>zShow archive listing)metavarhelpz-ez	--extractr   )rU  z<output_dir>zExtract archive into target dir)nargsrV  rW  z-tz--testzTest if a archive is validr   )argparseArgumentParsermainr)   add_mutually_exclusive_groupadd_argument
parse_argsr  r.   r   testr   r   r   )rd  rY  r  gr  r}  r#   r#   r$   r[    s.    



r[  __main__)N)r   r   r   NN)TTTTTF(  r)   r+  r\   r  rer  r`  r   r  binasciir   r   r   r   hashlibr   r   r   r	   pathlibr
   r   r   r   
subprocessr   r   r   r   r  r   r   Zcryptography.hazmat.backendsr   Z&cryptography.hazmat.primitives.ciphersr   r   r   r   ImportErrorZCrypto.Cipherr   __version____all__r@  rC  rE  rF  rJ  r   r  rj  ri  rw  ZPATH_SEPr  rL  r   r  r  r  ZRAR_BLOCK_OLD_RECOVERYr  r  rO  r  r  ZRAR_MAIN_LOCKr7  rM  ZRAR_MAIN_AUTHr  r9  rN  r  rT  rS  r   r  r  r  ZRAR_FILE_DICT64ZRAR_FILE_DICT128ZRAR_FILE_DICT256ZRAR_FILE_DICT512ZRAR_FILE_DICT1024ZRAR_FILE_DICT2048ZRAR_FILE_DICT4096r  r  r  r  r  r  ZRAR_FILE_EXTFLAGSrP  r  ZRAR_ENDARC_REVSPACErQ  r  r  r(  Z
RAR_OS_OS2r'  r  ZRAR_OS_MACOSZRAR_OS_BEOSrk  ZRAR_M1ZRAR_M2ZRAR_M3ZRAR_M4ZRAR_M5r   r  r  r  r  r  r  r  r  r  ZRAR5_BLOCK_FLAG_DEPENDS_PREVZ RAR5_BLOCK_FLAG_KEEP_WITH_PARENTr  r  r  r  ZRAR5_MAIN_FLAG_LOCKEDr  r  r  ZRAR5_FILE_FLAG_UNKNOWN_SIZEr  r*  r  r.  r0  r,  r2  r4  r6  r8  r:  r;  r<  r=  r>  r+  rA  rB  rE  re  rf  r  r@  r?  r!  rH  rI  rJ  rK  r  ZRAR5_OS_UNIXr  ZDOS_MODE_DIRZDOS_MODE_SYSTEMZDOS_MODE_HIDDENr)  r  r   r[   rf   platformr  r   r^   re   rg   Z
_BAD_CHARScompiler  r  ro  ro   r*   r+   r,   	Exceptionrt   rv   rw   rx   ry   rz   r{   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   UserWarningr   r-   r.   r/  r  r   r  r  r  r  r  r  r  r   r  	RawIOBaser/   r  rp  r  r_   rC  r  rF  r  rO  r  r  r  r  r  r  r)  r  r  r  r  r  r9  r  rb  rc  r  r  r  r   r  r  r  r   r  r  r  r?  r,  r  rm  r  r4  rL  rM  rP  rN  rO  rK  r  r[  r&   argvr#   r#   r#   r$   <module>   s  #



 '  l  a5    v? 4P +*@2





1



J
	



8        	            
