o
    b%                     @   s   d Z ddlZddlZddlZddlZG dd dejZG dd dZG dd deZ	G d	d
 d
eZ
dZdd Zdd ZdddZdS )z
An incremental approach to unzipping files.  This allows you to unzip a little
bit of a file at a time, which means you can report progress as a file unzips.
    Nc                   @   s   e Zd ZdZdd ZdS )ChunkingZipFilez~
    A L{zipfile.ZipFile} object which, with L{readfile}, also gives you access
    to a file-like object for each entry.
    c                 C   s"  | j dvr	td| jstd| |}| j|jd | jtj}|dd tj	kr2t
dttj|}| j|tj }|tj rP| j|tj  |jd@ r[|d}n|d	}||jkrot
d
|j|f |jtjkr{t| |jS |jtjkrt| |jS t
d|j|f )z3
        Return file-like object for name.
        )razread() requires mode "r" or "a"z3Attempt to read ZIP archive that was already closedr      z Bad magic number for file headeri   zutf-8cp437z3File name in directory "%s" and header "%s" differ.z-Unsupported compression method %d for file %s)modeRuntimeErrorfpgetinfoseekheader_offsetreadzipfilesizeFileHeaderstringFileHeader
BadZipfilestructunpackstructFileHeader_FH_FILENAME_LENGTH_FH_EXTRA_FIELD_LENGTH	flag_bitsdecodeorig_filenamecompress_type
ZIP_STOREDZipFileEntrycompress_sizeZIP_DEFLATEDDeflatedZipFileEntry)selfnamezinfofheaderfname	fname_str r&   :/usr/lib/python3/dist-packages/twisted/python/zipstream.pyreadfile   s>   






zChunkingZipFile.readfileN)__name__
__module____qualname____doc__r(   r&   r&   r&   r'   r      s    r   c                   @   sd   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZeZ	dd Z
dd Zdd Zdd Zdd ZdS )
_FileEntrya!  
    Abstract superclass of both compressed and uncompressed variants of
    file-like objects within a zip archive.

    @ivar chunkingZipFile: a chunking zip file.
    @type chunkingZipFile: L{ChunkingZipFile}

    @ivar length: The number of bytes within the zip file that represent this
    file.  (This is the size on disk, not the number of decompressed bytes
    which will result from reading it.)

    @ivar fp: the underlying file object (that contains pkzip data).  Do not
    touch this, please.  It will quite likely move or go away.

    @ivar closed: File-like 'closed' attribute; True before this file has been
    closed, False after.
    @type closed: L{bool}

    @ivar finished: An older, broken synonym for 'closed'.  Do not touch this,
    please.
    @type finished: L{int}
    c                 C   s&   || _ | j j| _|| _d| _d| _dS )zC
        Create a L{_FileEntry} from a L{ChunkingZipFile}.
        r   FN)chunkingZipFiler	   lengthfinishedclosedr    r.   r/   r&   r&   r'   __init__[   s
   

z_FileEntry.__init__c                 C   s   dS )zD
        Returns false because zip files should not be ttys
        Fr&   r    r&   r&   r'   isattye      z_FileEntry.isattyc                 C   s   d| _ d| _| `dS )z/
        Close self (file-like object)
        T   N)r1   r0   r	   r4   r&   r&   r'   closek   s   z_FileEntry.closec                    s6   d}t  fdddD ]}||7 }|dkr |S q|S )z
        Read a line.
            c                      s
     dS )Nr7   )r   r&   r4   r&   r'   <lambda>x   s   
 z%_FileEntry.readline.<locals>.<lambda>   
)iter)r    linebyter&   r4   r'   readlines   s   z_FileEntry.readlinec                 C   s   |   }|r|S t )zi
        Implement next as file does (like readline, except raises StopIteration
        at EOF)
        )r?   StopIteration)r    nextliner&   r&   r'   __next__~   s   z_FileEntry.__next__c                 C   s   t | S )z1
        Returns a list of all the lines
        )listr4   r&   r&   r'   	readlines   s   z_FileEntry.readlinesc                 C      | S z/
        Returns an iterator (so self)
        r&   r4   r&   r&   r'   
xreadlines   r6   z_FileEntry.xreadlinesc                 C   rE   rF   r&   r4   r&   r&   r'   __iter__   r6   z_FileEntry.__iter__c                 C   rE   Nr&   r4   r&   r&   r'   	__enter__   s   z_FileEntry.__enter__c                 C   s   |    d S rI   )r8   )r    exc_type	exc_value	tracebackr&   r&   r'   __exit__   s   z_FileEntry.__exit__N)r)   r*   r+   r,   r3   r5   r8   r?   rB   nextrD   rG   rH   rJ   rN   r&   r&   r&   r'   r-   C   s    
r-   c                   @   *   e Zd ZdZdd Zdd Zd	ddZdS )
r   zJ
    File-like object used to read an uncompressed entry in a ZipFile
    c                 C   s   t | || d| _d S )Nr   )r-   r3   	readBytesr2   r&   r&   r'   r3      s   
zZipFileEntry.__init__c                 C      | j S rI   )rQ   r4   r&   r&   r'   tell      zZipFileEntry.tellNc                 C   sv   |d u r
| j | j }|dks| jrdS | jjt|| j | j }|  jt|7  _| j| j ks6t||k r9d| _|S )Nr   r9   r7   )r/   rQ   r0   r.   r	   r   minlen)r    ndatar&   r&   r'   r      s   zZipFileEntry.readrI   r)   r*   r+   r,   r3   rS   r   r&   r&   r&   r'   r      s
    r   c                   @   rP   )
r   zE
    File-like object used to read a deflated entry in a ZipFile
    c                 C   s0   t | || d| _d| _td| _d| _d S )Nr   ir9   )r-   r3   returnedBytesrQ   zlibdecompressobjdecompbufferr2   r&   r&   r'   r3      s
   
zDeflatedZipFileEntry.__init__c                 C   rR   rI   )rZ   r4   r&   r&   r'   rS      rT   zDeflatedZipFileEntry.tellNc                 C   sd  | j rdS |d u rF| jg}|| j| jj| j| j	  || jd || j
  d| _d| _ d|}|  jt|7  _|S t| j|k r| jjt|d| j| j	 }|  j	t|7  _	|s| j| jd | j
  }d| _ d| _|  jt|7  _|S |  j| j|7  _t| j|k sM| jd | }| j|d  | _|  jt|7  _|S )Nr9      Zr7   i   )r0   r^   appendr]   
decompressr.   r	   r   r/   rQ   flushjoinrZ   rV   rU   )r    rW   resultrX   r&   r&   r'   r      sF   
zDeflatedZipFileEntry.readrI   rY   r&   r&   r&   r'   r      s
    r      c                 C   s,   d}t | }| D ]	}|t||7 }q
|S )zr
    Predict the number of chunks that will be extracted from the entire
    zipfile, given chunksize blocks.
    r   )r   infolistcountFileChunks)filename	chunksizetotalchunkszfinfor&   r&   r'   countZipFileChunks   s
   rm   c                 C   s(   t | j|\}}|dkr|d7 }|pdS )a9  
    Count the number of chunks that will result from the given C{ZipInfo}.

    @param zipinfo: a C{zipfile.ZipInfo} instance describing an entry in a zip
    archive to be counted.

    @return: the number of chunks present in the zip file.  (Even an empty file
    counts as one chunk.)
    @rtype: L{int}
    r   r7   )divmod	file_size)zipinfori   countextrar&   r&   r'   rg     s   rg   .   c              	   c   sl   t | d}tj|st| t| |}| }| }t||D ]\}}	|	j	t
@ }
tj||}|
rHtj|s@t| |d8 }|V  q#tj|d }tj|s[t| |sctj|s||}|	jdkrt|d8 }|V  t|d'}| |	jk r||}|| |d8 }|V  | |	jk sW d   n1 sw   Y  q#|t|	|8 }|V  q#dS )z
    Return a generator for the zipfile.  This implementation will yield after
    every chunksize uncompressed bytes, or at the end of a file, whichever
    comes first.

    The value it yields is the number of chunks left to unzip.
    r   r7   r   wbN)r   ospathexistsmakedirsrm   namelistrf   zipexternal_attrDIR_BITrc   splitr(   ro   openrS   r   writerg   )rh   	directory	overwriteri   czf	remainingnamesinfosentryrl   isdirffdirr	   outfilehunkr&   r&   r'   unzipIterChunky  sH   









r   )rs   r   rt   )r,   os.pathrv   r   r   r[   ZipFiler   r-   r   r   r}   rm   rg   r   r&   r&   r&   r'   <module>   s   3a8