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r‡t| |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   iñÿÿÿr9   )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 s�W d  ƒ n1 s£w   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