U
    Øcc˜L  ã                   @   sd  d 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 ddl	m
Z
mZmZmZmZ ddlmZ ddlmZ ddl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mZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@ eedœZAG dd„ de
eƒZBddlCmDZD dS )z
Server-mode SFTP support.
é    N)Úmd5Úsha1)Úutil)ÚBaseSFTPÚMessageÚSFTP_FAILUREÚSFTP_PERMISSION_DENIEDÚSFTP_NO_SUCH_FILE)ÚSFTPServerInterface)ÚSFTPAttributes)ÚDEBUG)ÚlongÚstring_typesÚbytes_typesÚb)ÚSubsystemHandler)%Ú
CMD_HANDLEÚ	SFTP_DESCÚ
CMD_STATUSÚSFTP_EOFÚCMD_NAMEÚSFTP_BAD_MESSAGEÚCMD_EXTENDED_REPLYÚSFTP_FLAG_READÚSFTP_FLAG_WRITEÚSFTP_FLAG_APPENDÚSFTP_FLAG_CREATEÚSFTP_FLAG_TRUNCÚSFTP_FLAG_EXCLÚ	CMD_NAMESÚCMD_OPENÚ	CMD_CLOSEÚSFTP_OKÚCMD_READÚCMD_DATAÚ	CMD_WRITEÚ
CMD_REMOVEÚ
CMD_RENAMEÚ	CMD_MKDIRÚ	CMD_RMDIRÚCMD_OPENDIRÚCMD_READDIRÚCMD_STATÚ	CMD_ATTRSÚ	CMD_LSTATÚ	CMD_FSTATÚCMD_SETSTATÚCMD_FSETSTATÚCMD_READLINKÚCMD_SYMLINKÚCMD_REALPATHÚCMD_EXTENDEDÚSFTP_OP_UNSUPPORTED)r   r   c                       sœ   e Zd ZdZefdd„Z‡ fdd„Zdd„ Z‡ fdd	„Ze	d
d„ ƒZ
e	dd„ ƒZdd„ Zd dd„Zd!dd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z‡  ZS )"Ú
SFTPServerzå
    Server-side SFTP subsystem support.  Since this is a `.SubsystemHandler`,
    it can be (and is meant to be) set as the handler for ``"sftp"`` requests.
    Use `.Transport.set_subsystem_handler` to activate this class.
    c                 O   sh   t  | ¡ t | |||¡ | ¡ }t | ¡ d ¡| _| ¡ | _	d| _
i | _i | _||f|ž|Ž| _dS )a  
        The constructor for SFTPServer is meant to be called from within the
        `.Transport` as a subsystem handler.  ``server`` and any additional
        parameters or keyword parameters are passed from the original call to
        `.Transport.set_subsystem_handler`.

        :param .Channel channel: channel passed from the `.Transport`.
        :param str name: name of the requested subsystem.
        :param .ServerInterface server:
            the server object associated with this channel and subsystem
        :param sftp_si:
            a subclass of `.SFTPServerInterface` to use for handling individual
            requests.
        z.sftpé   N)r   Ú__init__r   Zget_transportr   Z
get_loggerZget_log_channelÚloggerZget_hexdumpZultra_debugÚnext_handleÚ
file_tableÚfolder_tableÚserver)ÚselfÚchannelÚnamer>   Zsftp_siÚlargsÚkwargsÚ	transport© rE   ú8/tmp/pip-unpacked-wheel-rglolp_m/paramiko/sftp_server.pyr9   ^   s    

zSFTPServer.__init__c                    sf   t t|ƒtƒr>|D ](}tt| ƒ |d| j ¡  d | ¡ qn$tt| ƒ |d| j ¡  d | ¡ d S )Nz[chan z] )Ú
issubclassÚtypeÚlistÚsuperr7   Ú_logÚsockÚget_name)r?   ÚlevelÚmsgÚm©Ú	__class__rE   rF   rK   €   s    
 ÿ
 ÿzSFTPServer._logc           	   
   C   s8  || _ |  td |¡¡ |  ¡  | j ¡  z|  ¡ \}}W nl tk
r\   |  td¡ Y d S  t	k
r¦ } z.|  tdt
|ƒ ¡ |  tt ¡ ¡ W Y ¢d S d }~X Y nX t|ƒ}| ¡ }z|  |||¡ W q* t	k
r0 } zF|  tdt
|ƒ ¡ |  tt ¡ ¡ z|  |t¡ W n   Y nX W 5 d }~X Y q*X q*d S )Nz#Started sftp server on channel {!r}zEOF -- end of sessionzException on channel: z Exception in server processing: )rL   rK   r   ÚformatZ_send_server_versionr>   Zsession_startedZ_read_packetÚEOFErrorÚ	ExceptionÚstrr   Z
tb_stringsr   Úget_intÚ_processÚ_send_statusr   )	r?   rA   rD   r@   ÚtÚdataÚerO   Úrequest_numberrE   rE   rF   Ústart_subsystem‹   s0    
zSFTPServer.start_subsystemc                    sX   | j  ¡  tt| ƒ ¡  | j ¡ D ]}| ¡  q"| j ¡ D ]}| ¡  q:i | _i | _d S )N)	r>   Zsession_endedrJ   r7   Úfinish_subsystemr<   ÚvaluesÚcloser=   )r?   ÚfrQ   rE   rF   r_   §   s    


zSFTPServer.finish_subsystemc                 C   s.   | t jkrtS | t jks"| t jkr&tS tS dS )au  
        Convert an errno value (as from an ``OSError`` or ``IOError``) into a
        standard SFTP result code.  This is a convenience function for trapping
        exceptions in server code and returning an appropriate result.

        :param int e: an errno code, as from ``OSError.errno``.
        :return: an `int` SFTP error code like ``SFTP_NO_SUCH_FILE``.
        N)ÚerrnoÚEACCESr   ÚENOENTÚENOTDIRr	   r   )r\   rE   rE   rF   Úconvert_errno³   s
    

zSFTPServer.convert_errnoc              	   C   s”   t jdkrB|j|j@ r$t | |j¡ |j|j@ rBt | |j	|j
¡ |j|j@ rbt | |j|jf¡ |j|j@ rt| dƒ}| |j¡ W 5 Q R X dS )a:  
        Change a file's attributes on the local filesystem.  The contents of
        ``attr`` are used to change the permissions, owner, group ownership,
        and/or modification & access time of the file, depending on which
        attributes are present in ``attr``.

        This is meant to be a handy helper function for translating SFTP file
        requests into local file operations.

        :param str filename:
            name of the file to alter (should usually be an absolute path).
        :param .SFTPAttributes attr: attributes to change.
        Úwin32zw+N)ÚsysÚplatformÚ_flagsZFLAG_PERMISSIONSÚosÚchmodÚst_modeZFLAG_UIDGIDÚchownÚst_uidÚst_gidZFLAG_AMTIMEÚutimeÚst_atimeÚst_mtimeZ	FLAG_SIZEÚopenÚtruncateÚst_size)ÚfilenameÚattrrb   rE   rE   rF   Úset_file_attrÆ   s    
zSFTPServer.set_file_attrc                 G   sœ   t ƒ }| |¡ |D ]v}t|tƒr.| |¡ qt|tƒrD| |¡ qt|ttfƒr^| |¡ qt	|ƒt
krv| |¡ qtd |t	|ƒ¡ƒ‚q|  ||¡ d S )Nzunknown type for {!r} type {!r})r   Úadd_intÚ
isinstancer   Z	add_int64Úintr   r   Ú
add_stringrH   r   Ú_packrU   rS   Ú_send_packet)r?   r]   rZ   ÚargrO   ÚitemrE   rE   rF   Ú	_responseã   s    


ÿzSFTPServer._responseFc                 C   sz   t t|ƒtƒs|  ||¡ d S | td | j¡ƒ¡ |  jd7  _|rV|| j| 	¡ < n|| j
| 	¡ < |  |t| 	¡ ¡ d S )Nzhx{:d}r8   )rG   rH   Ú
SFTPHandlerY   Z	_set_namer   rS   r;   r=   Z	_get_namer<   rƒ   r   )r?   r]   ÚhandleÚfolderrE   rE   rF   Ú_send_handle_responseõ   s    z SFTPServer._send_handle_responseNc                 C   sD   |d kr.zt | }W n tk
r,   d}Y nX |  |t||d¡ d S )NÚUnknownÚ )r   Ú
IndexErrorrƒ   r   )r?   r]   ÚcodeÚdescrE   rE   rF   rY     s    
zSFTPServer._send_statusc                 C   sL   | j  |¡}tt|ƒtƒr<tƒ }| |¡ |  ||d¡ d S |  ||¡ d S )NT)	r>   Zlist_folderrG   rH   rI   r„   Z
_set_filesr‡   rY   )r?   r]   ÚpathÚrespr†   rE   rE   rF   Ú_open_folder  s    
zSFTPServer._open_folderc                 C   s|   |  ¡ }t|ƒdkr$|  |t¡ d S tƒ }| |¡ | t|ƒ¡ |D ]$}| |j¡ | |¡ | |¡ qF|  	t
|¡ d S )Nr   )Z_get_next_filesÚlenrY   r   r   r{   r~   rx   r   r€   r   )r?   r]   r†   ÚflistrO   ry   rE   rE   rF   Ú_read_folder  s    

zSFTPServer._read_folderc                 C   sÂ  |  ¡ }| ¡ }| ¡ }| ¡ }| ¡ }|| jkrD|  |td¡ d S | j| }|D ]}	|	tkrR|	}
t|	 } q‚qR|  |td¡ d S |dkr¼| 	¡ }t
t|ƒtƒs²|  ||d¡ d S |j| }|dkrÈ|}|dk râ|  |td¡ d S tƒ }|}||| k r„t||| | ƒ}t|dƒ}d}|ƒ }||k rv| ||¡}t|tƒsT|  ||d¡ d S | |¡ |t|ƒ7 }||7 }q || ¡ 7 }qìtƒ }| |¡ | d	¡ | |
¡ | |¡ |  t|¡ d S )
NúInvalid handlezNo supported hash types foundr   zUnable to stat fileé   zBlock size too smalli   zUnable to hash fileú
check-file)Ú
get_binaryZget_listÚ	get_int64rW   r<   rY   r   Ú_hash_classr   ÚstatrG   rH   r   rw   ÚbytesÚminÚreadr|   r   Úupdater   Údigestr   r{   r~   Z	add_bytesr€   r   )r?   r]   rO   r…   Zalg_listÚstartÚlengthÚ
block_sizerb   ÚxZalgnameZalgÚstZsum_outÚoffsetZblocklenZchunklenÚcountZhash_objr[   rE   rE   rF   Ú_check_file%  s‚    
  ÿ
  ÿ
  ÿ

  ÿ




zSFTPServer._check_filec                 C   sz   |t @ r|t@ rtj}n|t@ r(tj}ntj}|t@ r@|tjO }|t@ rR|tj	O }|t
@ rd|tjO }|t@ rv|tjO }|S )z;convert SFTP-style open() flags to Python's os.open() flags)r   r   rl   ÚO_RDWRÚO_WRONLYÚO_RDONLYr   ÚO_APPENDr   ÚO_CREATr   ÚO_TRUNCr   ÚO_EXCL)r?   ZpflagsÚflagsrE   rE   rF   Ú_convert_pflagsh  s    



zSFTPServer._convert_pflagsc                 C   sÀ  |   td t| ¡¡ |tkrZ| ¡ }|  | ¡ ¡}t 	|¡}|  
|| j |||¡¡ nb|tkrÎ| ¡ }|| jkrŒ| j|= |  |t¡ d S || jkr¼| j|  ¡  | j|= |  |t¡ d S |  |td¡ nî|tkrl| ¡ }| ¡ }| ¡ }	|| jkr|  |td¡ d S | j|  ||	¡}
t|
ttfƒr\t|
ƒdkrL|  |t¡ n|  |t|
¡ n|  ||
¡ nP|tkrÊ| ¡ }| ¡ }| ¡ }
|| jkr¬|  |td¡ d S |  || j|   ||
¡¡ nò|t!krô| ¡ }|  || j "|¡¡ nÈ|t#kr(| ¡ }| ¡ }|  || j $||¡¡ n”|t%kr^| ¡ }t 	|¡}|  || j &||¡¡ n^|t'krˆ| ¡ }|  || j (|¡¡ n4|t)krª| ¡ }|  *||¡ d S |t+krô| ¡ }|| jkrÚ|  |td¡ d S | j| }|  ,||¡ nÈ|t-krB| ¡ }| j .|¡}t/t0|ƒtƒr2|  |t1|¡ n|  ||¡ nz|t2kr| ¡ }| j 3|¡}t/t0|ƒtƒr€|  |t1|¡ n|  ||¡ n,|t4krþ| ¡ }|| jkrÀ|  |td¡ d S | j|  .¡ }t/t0|ƒtƒrî|  |t1|¡ n|  ||¡ n¾|t5kr4| ¡ }t 	|¡}|  || j 6||¡¡ nˆ|t7krŠ| ¡ }t 	|¡}|| jkrn|  |td¡ d S |  || j|  6|¡¡ n2|t8krÞ| ¡ }| j 9|¡}t|ttfƒrÐ|  |t:d|dtƒ ¡ n|  ||¡ nÞ|t;kr| ¡ }| ¡ }|  || j <||¡¡ n¬|t=krF| ¡ }| j >|¡}|  |t:d|dtƒ ¡ nv|t?kr°| ¡ }|dkrp|  @||¡ n>|dkr¢| ¡ }| ¡ }|  || j A||¡¡ n|  |tB¡ n|  |tB¡ d S )NzRequest: {}r“   r   r8   r‰   r•   zposix-rename@openssh.com)CrK   r   rS   r   r    Zget_textr¯   rW   r   Z	_from_msgr‡   r>   ru   r!   r–   r=   rY   r"   r<   ra   r   r#   r—   rœ   r|   r   r   r   r   rƒ   r$   r%   Úwriter&   Úremover'   Úrenamer(   Úmkdirr)   Úrmdirr*   r   r+   r’   r,   r™   rG   rH   r-   r.   Úlstatr/   r0   Zchattrr1   r2   Úreadlinkr   r3   Úsymlinkr4   Úcanonicalizer5   r¦   Zposix_renamer6   )r?   rZ   r]   rO   r   r®   ry   r…   r¤   r    r[   ÚoldpathÚnewpathr†   rŽ   Útarget_pathZrpathÚtagrE   rE   rF   rX   z  s`   
 ÿ

  ÿ
  ÿ
  ÿ ÿ

 ÿ




  ÿ



  ÿ



  ÿ ÿ
     ÿ
 ÿ
     ÿ


 ÿzSFTPServer._process)F)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r
   r9   rK   r^   r_   Ústaticmethodrg   rz   rƒ   r‡   rY   r   r’   r¦   r¯   rX   Ú__classcell__rE   rE   rQ   rF   r7   W   s$   û
"




Cr7   )r„   )ErÀ   rl   rc   ri   Úhashlibr   r   Zparamikor   Zparamiko.sftpr   r   r   r   r	   Zparamiko.sftp_sir
   Zparamiko.sftp_attrr   Zparamiko.commonr   Zparamiko.py3compatr   r   r   r   Zparamiko.serverr   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/   r0   r1   r2   r3   r4   r5   r6   r˜   r7   Zparamiko.sftp_handler„   rE   rE   rE   rF   Ú<module>   s$   œ(
   G