o
    >h                     @   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m	Z	m
Z
 ddlmZ ddlmZ ddlmZ ddlm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% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/ e-dZ0e-dZ1e0rz.ddl2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 ddl:m;Z;m<Z< ddl=m>Z> ddlm?Z? W n	 e@y   Y nw dZAde1e0eBedfv rdZAeeAdG d d! d!e/ZCG d"d# d#e/ZDG d$d% d%e!ZEG d&d' d'ZFG d(d) d)ZGeeG d*d+ d+e	ZHeeAdG d,d- d-e/ZIG d.d/ d/ZJG d0d1 d1ejKZLG d2d3 d3eZMeeAdG d4d5 d5eMZNeeAdG d6d7 d7eMZOeeAdee+d8 d9ee+d: d;G d<d= d=eMZPdS )>z*
Tests for L{twisted.conch.scripts.cftp}.
    N)BytesIOTextIOWrapper)skipIf)implementer)ls)	ISFTPFile)FileTransferTestAvatarSFTPTestBase)portal)defererror
interfacesprotocolreactor)Clock)StringTransport)getProcessOutputAndValue)log)UserDatabase)FilePath)which)requireModule)TestCasecryptographyztwisted.conch.unix)cftp)
SSHSession)filetransfer)EXTENDED_DATA_STDERR)
test_conchtest_ssh)	FakeStdio)FileTransferForTestAvatarFTz*don't run w/o spawnProcess or cryptographyc                   @   s.   e Zd ZdZd
ddZd
ddZd
dd	ZdS )SSHSessionTestsz=
    Tests for L{twisted.conch.scripts.cftp.SSHSession}.
    returnNc                 C   s<   t  | _t | _| j| j_t | _t| j| _| j| j_d S N)r    stdior   channelr   stderrBufferr   stderrself r+   |/var/www/vedio/testing/chatpythonscript.ninositsolution.com/env/lib/python3.10/site-packages/twisted/conch/test/test_cftp.pysetUp>   s   
zSSHSessionTests.setUpc                 C   s   | j   | | jj dS )z|
        L{twisted.conch.scripts.cftp.SSHSession.eofReceived} loses the write
        half of its stdio connection.
        N)r&   eofReceived
assertTruer%   writeConnLostr)   r+   r+   r,   test_eofReceivedF   s   
z SSHSessionTests.test_eofReceivedc                 C   s:   d}| d}| jt|d  | | j |d  dS )z
        L{twisted.conch.scripts.cftp.SSHSession.extReceived} decodes
        stderr data using UTF-8 with the "backslashescape" error handling and
        writes the result to its own stderr.
        u   ☃utf-8   s   \xffN)encoder&   extReceivedr   assertEqualr'   getvalue)r*   	errorText
errorBytesr+   r+   r,   test_extReceivedStderrN   s   
z&SSHSessionTests.test_extReceivedStderr)r#   N)__name__
__module____qualname____doc__r-   r1   r:   r+   r+   r+   r,   r"   8   s
    

r"   c                
   @   s   e Zd ZdZeedddu rdZdd Zdd Zd	d
 Z	dd Z
dd Ze Zz!z	eejd W n ejy>   dZY nw dZW eeje neeje w eeddd Zdd ZdS )ListingTestsz
    Tests for L{lsLine}, the function which generates an entry for a file or
    directory in an SFTP I{ls} command's output.
    tzsetNz8Cannot test timestamp formatting code without time.tzsetc                    sj   d _  fdd} td| dtjv r* tjtjdtjd   tj	 dS dd } | dS )	zo
        Patch the L{ls} module's time function so the results of L{lsLine} are
        deterministic.
        i[c                      s    j S r$   )nowr+   r)   r+   r,   fakeTimep   s   z$ListingTests.setUp.<locals>.fakeTimetimeTZc                   S   s,   zt jd= W n	 ty   Y nw t  d S )NrD   )osenvironKeyErrorrC   r@   r+   r+   r+   r,   cleanup|   s   z#ListingTests.setUp.<locals>.cleanupN)
rA   patchr   rE   rF   
addCleanupoperatorsetitemrC   r@   )r*   rB   rH   r+   r)   r,   r-   i   s   
zListingTests.setUpc                 C   s   |t jd< t  td|S )zl
        Call L{ls.lsLine} after setting the timezone to C{timezone} and return
        the result.
        rD   foo)rE   rF   rC   r@   r   lsLine)r*   timezonestatr+   r+   r,   _lsInTimezone   s   
zListingTests._lsInTimezonec                 C   T   | j d }tdddddddd|df
}| | d|d | | d|d dS )z
        A file with an mtime six months (approximately) or more in the past has
        a listing including a low-resolution timestamp.
        r   America/New_Yorkz;!---------    0 0        0               0 Apr 26  1973 fooPacific/Aucklandz;!---------    0 0        0               0 Apr 27  1973 fooNrA   rE   stat_resultr6   rQ   r*   thenrP   r+   r+   r,   test_oldFile      


zListingTests.test_oldFilec                 C   X   | j d d }tdddddddd|df
}| | d|d | | d|d dS )	
        A file with a high-resolution timestamp which falls on a day of the
        month which can be represented by one decimal digit is formatted with
        one padding 0 to preserve the columns which come after it.
        rS   i r   rT   z;!---------    0 0        0               0 May 01  1973 foorU   z;!---------    0 0        0               0 May 02  1973 fooNrV   rX   r+   r+   r,   test_oldSingleDigitDayOfMonth      

z*ListingTests.test_oldSingleDigitDayOfMonthc                 C   rR   )z
        A file with an mtime fewer than six months (approximately) in the past
        has a listing including a high-resolution timestamp excluding the year.
        逛z r   rT   ;!---------    0 0        0               0 Aug 28 17:33 foorU   ;!---------    0 0        0               0 Aug 29 09:33 fooNrV   rX   r+   r+   r,   test_newFile   r[   zListingTests.test_newFile
es_AR.UTF8TFz'The es_AR.UTF8 locale is not installed.c                 C   s|   | j d }tdddddddd|df
}t }ttjd | tjtj| | | 	d|d | | 	d|d dS )	zC
        The month name in the date is locale independent.
        r`   r   rd   rT   ra   rU   rb   N)
rA   rE   rW   locale	getlocale	setlocaleLC_ALLrJ   r6   rQ   )r*   rY   rP   currentLocaler+   r+   r,   test_localeIndependent   s   


z#ListingTests.test_localeIndependentc                 C   r\   )	r]   r`   i F r   rT   z;!---------    0 0        0               0 Sep 01 17:33 foorU   z;!---------    0 0        0               0 Sep 02 09:33 fooNrV   rX   r+   r+   r,   test_newSingleDigitDayOfMonth   r_   z*ListingTests.test_newSingleDigitDayOfMonth)r;   r<   r=   r>   getattrrC   skipr-   rQ   rZ   r^   rc   re   rf   ri   rg   rh   Error
localeSkipr   rj   rk   r+   r+   r+   r,   r?   `   s,     
r?   c                       s    e Zd ZdZ fddZ  ZS )InMemorySSHChannelzp
    Minimal implementation of a L{SSHChannel} like class which only reads and
    writes data from memory.
    c                    s   || _ d| _t   dS )zt
        @param conn: The SSH connection associated with this channel.
        @type conn: L{SSHConnection}
        r   N)connlocalClosedsuper__init__)r*   rq   	__class__r+   r,   rt     s   zInMemorySSHChannel.__init__)r;   r<   r=   r>   rt   __classcell__r+   r+   ru   r,   rp     s    rp   c                   @   (   e Zd ZdZdd Zdd Zdd ZdS )	FilesystemAccessExpectationszC
    A test helper used to support expected filesystem access.
    c                 C   s
   i | _ d S r$   _cacher)   r+   r+   r,   rt        
z%FilesystemAccessExpectations.__init__c                 C   s   || j ||f< dS )z

        @param path: Path at which the stream is requested.
        @type path: L{str}

        @param path: Flags with which the stream is requested.
        @type path: L{str}

        @param stream: A stream.
        @type stream: C{File}
        Nrz   )r*   pathflagsstreamr+   r+   r,   put  s   z FilesystemAccessExpectations.putc                 C   s   | j ||fS )a  
        Remove a stream from the memory.

        @param path: Path at which the stream is requested.
        @type path: L{str}

        @param path: Flags with which the stream is requested.
        @type path: L{str}

        @return: A stream.
        @rtype: C{File}
        )r{   pop)r*   r}   r~   r+   r+   r,   r   (  s   z FilesystemAccessExpectations.popN)r;   r<   r=   r>   rt   r   r   r+   r+   r+   r,   ry     s
    ry   c                   @   s    e Zd ZdZdd Zdd ZdS )InMemorySFTPClienta'  
    A L{filetransfer.FileTransferClient} which does filesystem operations in
    memory, without touching the local disc or the network interface.

    @ivar _availableFiles: File like objects which are available to the SFTP
        client.
    @type _availableFiles: L{FilesystemRegister}
    c                 C   s    t | | _ddd| _|| _d S )N   
   )requests
buffersize)rp   	transportoptions_availableFiles)r*   availableFilesr+   r+   r,   rt   B  s
   

zInMemorySFTPClient.__init__c                 C   s   | j ||S )z}
        @see: L{filetransfer.FileTransferClient.openFile}.

        Retrieve and remove cached file based on flags.
        )r   r   )r*   filenamer~   attrsr+   r+   r,   openFileJ  s   zInMemorySFTPClient.openFileN)r;   r<   r=   r>   rt   r   r+   r+   r+   r,   r   8  s    	r   c                   @   sH   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S )InMemoryRemoteFilez;
    An L{ISFTPFile} which handles all data in memory.
    c                 C   s   || _ t|  dS )zL
        @param name: Name of this file.
        @type name: L{str}
        N)namer   rt   )r*   r   r+   r+   r,   rt   Y  s   zInMemoryRemoteFile.__init__c                 C   s   |  | | | t| S )z/
        @see: L{ISFTPFile.writeChunk}
        )seekwriter   succeed)r*   startdatar+   r+   r,   
writeChunka  s   


zInMemoryRemoteFile.writeChunkc                 C   s
   d| _ dS )zo
        @see: L{ISFTPFile.writeChunk}

        Keeps data after file was closed to help with testing.
        TN)_closedr)   r+   r+   r,   closei     
zInMemoryRemoteFile.closec                 C      d S r$   r+   r)   r+   r+   r,   getAttrsq     zInMemoryRemoteFile.getAttrsc                 C   r   r$   r+   )r*   offsetlengthr+   r+   r,   	readChunku  r   zInMemoryRemoteFile.readChunkc                 C   r   r$   r+   )r*   r   r+   r+   r,   setAttrsy  r   zInMemoryRemoteFile.setAttrsc                 C   s
   t | S )zb
        Get current data of file.

        Allow reading data event when file is closed.
        )r   r7   r)   r+   r+   r,   r7   }  r   zInMemoryRemoteFile.getvalueN)r;   r<   r=   r>   rt   r   r   r   r   r   r7   r+   r+   r+   r,   r   S  s    r   c                   @   s   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dZd*dd Zd!d" Zd#d$ Zd%d& Zd'd( ZdS )+StdioClientTestsz(
    Tests for L{cftp.StdioClient}.
    c                 C   sT   t  | _t| j}t|| _d| j_t  | _| j_	| 
dd | jjj| j_dS )zm
        Create a L{cftp.StdioClient} hooked up to dummy transport and a fake
        user database.
        /i     N)ry   fakeFilesystemr   r   StdioClientclientcurrentDirectoryr   database_pwdsetKnownConsoleSizer   )r*   
sftpClientr+   r+   r,   r-     s   
zStdioClientTests.setUpc              	   C   s@   | j t dt dddtj | j	d}|
| jd |S )zs
        The I{exec} command runs its arguments locally in a child process
        using the user's shell.
        secret  rM   barzexec print(1 + 2)s   3
)r   addUsergetpassgetuserrE   getuidsys
executabler   _dispatchCommandaddCallbackr6   r*   dr+   r+   r,   	test_exec  s   zStdioClientTests.test_execc              	   C   >   | j t dt dddd | jd}|| j	d |S )zr
        If the local user has no shell, the I{exec} command runs its arguments
        using I{/bin/sh}.
        r   r   rM   r    zexec echo hello   hello

r   r   r   r   rE   r   r   r   r   r6   r   r+   r+   r,   test_execWithoutShell  s   z&StdioClientTests.test_execWithoutShellc              	   C   r   )zO
        The I{exec} command is run for lines which start with C{"!"}.
        r   r   rM   r   z/bin/shz!echo hellor   r   r   r+   r+   r,   	test_bang  s   zStdioClientTests.test_bangc                    s2   ddl G  fddd}| td|  dS )a  
        For the duration of this test, patch C{cftp}'s C{fcntl} module to return
        a fixed width and height.

        @param width: the width in characters
        @type width: L{int}
        @param height: the height in characters
        @type height: L{int}
        r   Nc                       s   e Zd Z fddZdS )z7StdioClientTests.setKnownConsoleSize.<locals>.FakeFcntlc                    s&   |j kr
| d td ddS )Nz#Only window-size queries supported.4Hr   )
TIOCGWINSZfailstructpack)r*   fdoptmutateheightttywidthr+   r,   ioctl  s   

z=StdioClientTests.setKnownConsoleSize.<locals>.FakeFcntl.ioctlN)r;   r<   r=   r   r+   r   r+   r,   	FakeFcntl  s    r   fcntl)r   rI   r   )r*   r   r   r   r+   r   r,   r     s   z$StdioClientTests.setKnownConsoleSizec                 C   s   |  dd t  }| j_td}d|_t|}d|_|	 }|
d | jd7  _| j|| d}| | jj | d	S )
a(  
        L{StdioClient._printProgressBar} prints a progress description,
        including percent done, amount transferred, transfer rate, and time
        remaining, all based the given start time, the given L{FileWrapper}'s
        progress information and the reactor's current time.
        r   "      x   samplei (  g       @i   s#   b'sample' 40% 4.0kB 2.0kBps 00:03 N)r   r   r   r   r   r   r   FileWrappersizesecondsadvancetotal_printProgressBarr6   r   valuer*   clockwrappedwrapper	startTimeresultr+   r+   r,   test_printProgressBarReporting  s   	

z/StdioClientTests.test_printProgressBarReportingc                 C   sd   |  dd t  }| j_td}d|_t|}| }| j	|| d}| 
| jj | dS )z
        L{StdioClient._printProgressBar} prints a progress description that
        indicates 0 bytes transferred if no bytes have been transferred and no
        time has passed.
        r   r   r   r   s!   b'sample'  0% 0.0B 0.0Bps 00:00 N)r   r   r   r   r   r   r   r   r   r   r6   r   r   r   r+   r+   r,   test_printProgressBarNoProgress  s   
z0StdioClientTests.test_printProgressBarNoProgressc                 C   sL   |  dd t }d|_t|}| j|d d}| || jj	  dS )z5
        Print the progress for empty files.
        r   r   s
   empty-filer   s%   b'empty-file'100% 0.0B 0.0Bps 00:00 N)
r   r   r   r   r   r   r   r6   r   r   )r*   r   r   r   r+   r+   r,   test_printProgressBarEmptyFile  s   
z/StdioClientTests.test_printProgressBarEmptyFilec                 C      | j d}| d| dS )zK
        Returns empty value for both filename and remaining data.
        z  )r   r   Nr   _getFilenamer6   r*   r   r+   r+   r,   test_getFilenameEmpty  s   z&StdioClientTests.test_getFilenameEmptyc                 C   r   )zd
        Returns empty value for remaining data when line contains
        only a filename.
        
only-local)r   r   Nr   r   r+   r+   r,   test_getFilenameOnlyLocal     z*StdioClientTests.test_getFilenameOnlyLocalc                 C   r   )ze
        Returns filename and remaining data striped of leading and trailing
        spaces.
        z local  remote file  )localzremote fileNr   r   r+   r+   r,   test_getFilenameNotQuoted#  r   z*StdioClientTests.test_getFilenameNotQuotedc                 C   r   )z
        Returns filename and remaining data not striped of leading and trailing
        spaces when quoted paths are requested.
        z" " local file "  " remote  file " )z local file z" remote  file "Nr   r   r+   r+   r,   test_getFilenameQuoted,  r   z'StdioClientTests.test_getFilenameQuotedN    c                 C   sJ   |du r|   }t|d}|| W d   |S 1 sw   Y  |S )ab  
        Create a local file and return its path.

        When `path` is L{None}, it will create a new temporary file.

        @param path: Optional path for the new file.
        @type path: L{str}

        @param content: Content to be written in the new file.
        @type content: L{bytes}

        @return: Path to the newly create file.
        Nwb)mktempopenr   )r*   r}   contentfiler+   r+   r,   makeFile5  s   
zStdioClientTests.makeFileFc                 C   sh  | j j }|d}|d}g }g }|D ]\}}}g }	|D ]}
|	| d|
  q|	d| d|  ||	 |ddd}|dd	 }|d	 d
d
}|| g }|dd	 D ]$}
|
 	ddd }
|
 dd}
||
d  d|
d    qd||d	  || q|r| 
t|t| n| 
|| | 
dt|d dS )a  
        Check output of cftp client for a put request.


        @param transfers: List with tuple of (local, remote, progress).
        @param randomOrder: When set to C{True}, it will ignore the order
            in which put reposes are received

        r2   z
 zTransferred z to r   N
   r   z5There are still put responses which were not checked.)r   r   r   decodesplitappendr   stripextendrsplitr6   sortedlen)r*   	transfersrandomOrderoutputexpectedOutputactualOutputr   remoteexpectedexpectedTransferlineprogressPartsactuallastactualTransferr+   r+   r,   checkPutMessageI  s<   




"z StdioClientTests.checkPutMessagec                 C   s   d}| j |d}tjtjB tjB }tjdtj|}t	|}| j
||t| d| jjjd< | j|}| | | ||  | |j | ||g dfg dS )z
        A name based on local path is used when remote path is not
        provided.

        The progress is updated while chunks are transferred.
        s   Test
Content)r   r   r   r   )z	76% 10.0B
100% 13.0Br  N)r   r   	FXF_WRITE	FXF_CREAT	FXF_TRUNCrE   r}   joinbasenamer   r   r   r   r   r   r   cmd_PUTsuccessResultOfr6   r7   r/   r   r  )r*   r   	localPathr~   
remoteName
remoteFiledeferredr+   r+   r,   test_cmd_PUTSingleNoRemotePath  s   
z/StdioClientTests.test_cmd_PUTSingleNoRemotePathc                 C   s   |   }tjtjB tjB }d}t|}| j||t	| | j
| d| d}| | | ||dgfg | |j | d|  dS )z
        Remote path is extracted from first filename after local file.

        Any other data in the line is ignored.
        z/remote-pathr   z ignored	100% 0.0Br   N)r   r   r  r  r  r   r   r   r   r   r   r  r  r  r/   r   r6   r7   )r*   r  r~   r  r  r  r+   r+   r,   test_cmd_PUTSingleRemotePath  s   
z-StdioClientTests.test_cmd_PUTSingleRemotePathc                 C   s  |   }tj|}d}tj|}| j tj||d}tjtjB tj	B }d| }d| }t
|}	t
|}
| j||t|	 | j||t|
 | jtj|d}| | | |	j | d|	  | |
j | d|
  | j||dgf||dgfgdd d	S )
z
        When a gobbing expression is used local files are transferred with
        remote file names based on local names.
        second-namer}   r   *r   r  Tr  N)r   rE   r}   r  dirnamer  r   r  r  r  r   r   r   r   r   r   r  r  r/   r   r6   r7   r  )r*   first	firstName
secondNameparentsecondr~   firstRemotePathsecondRemotePathfirstRemoteFilesecondRemoteFiler  r+   r+   r,    test_cmd_PUTMultipleNoRemotePath  s4   





z1StdioClientTests.test_cmd_PUTMultipleNoRemotePathc                 C   s   |   }tj|}d}tj|}| j tj||d}tjtjB tj	B }t
|}t
|}d| }	d| }
| j|	|t| | j|
|t| | jdtj|d}| | | |j | d|  | |j | d|  | j||dgf||dgfgdd	 d
S )z
        When a gobbing expression is used local files are transferred with
        remote file names based on local names.
        when a remote folder is requested remote paths are composed from
        remote path and local filename.
        r  r  z/remote/z	{} remoter  r   r  Tr   N)r   rE   r}   r  r!  r  r   r  r  r  r   r   r   r   r   r   r  formatr  r/   r   r6   r7   r  )r*   r"  r#  r$  r%  r&  r~   r)  r*  r'  r(  r  r+   r+   r,   "test_cmd_PUTMultipleWithRemotePath  s4   





z3StdioClientTests.test_cmd_PUTMultipleWithRemotePath)Nr   )F)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     s(    		
	
=#r   c                   @   s   e Zd Zdd Zdd ZdS )FileTransferTestRealmc                 C   s
   || _ d S r$   )testDir)r*   r/  r+   r+   r,   rt     r|   zFileTransferTestRealm.__init__c                 G   s   t | j}|d |dd fS )Nr   c                   S   r   r$   r+   r+   r+   r+   r,   <lambda>   s    z5FileTransferTestRealm.requestAvatar.<locals>.<lambda>)r   r/  )r*   avatarIDmindr   ar+   r+   r,   requestAvatar  s   
z#FileTransferTestRealm.requestAvatarN)r;   r<   r=   rt   r4  r+   r+   r+   r,   r.    s    r.  c                   @   s`   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S )SFTPTestProcessz
    Protocol for testing cftp. Provides an interface between Python (where all
    the tests are) and the cftp client process (which does the work that is
    being tested).
    c                 C   s$   |    || _d| _d| _d| _dS )zr
        @param onOutReceived: A L{Deferred} to be fired as soon as data is
        received from stdout.
        NF)clearBufferonOutReceivedonProcessEnd_expectingCommand_processEnded)r*   r7  r+   r+   r,   rt   
  s
   
zSFTPTestProcess.__init__c                 C   s   d| _ g | _d| _dS )zR
        Clear any buffered data received from stdout. Should be private.
        r   N)buffer_linesReceived_lineBufferr)   r+   r+   r,   r6    s   
zSFTPTestProcess.clearBufferc                 C   sr   t d|  | j| d}|d| _| j| | jdur,| jd}| _|| |  j	|7  _	| 
  dS )zO
        Called by Twisted when the cftp client prints data to stdout.
        zgot %r   
r   N)r   msgr=  r   r   r<  r   r7  callbackr;  _checkForCommand)r*   r   linesr   r+   r+   r,   outReceived  s   

zSFTPTestProcess.outReceivedc                 C   sf   d}| j r/| j|kr1d| j}||r|t|d  }|   | j d }| _ || d S d S d S )Ns   cftp> r>  )r9  r=  r  r<  
startswithr   r6  r@  )r*   promptbufr   r+   r+   r,   rA  .  s   
z SFTPTestProcess._checkForCommandc                 C   s   t d|  dS )zO
        Called by Twisted when the cftp client prints data to stderr.
        zerr: %sN)r   r?  )r*   r   r+   r+   r,   errReceived8  s   zSFTPTestProcess.errReceivedc                 C   s   | j S )zQ
        Return the contents of the buffer of data received from stdout.
        )r;  r)   r+   r+   r,   	getBuffer>  s   zSFTPTestProcess.getBufferc                 C   s<   t  | _|   t|tr|d}| j|d  | jS )a  
        Issue the given command via the cftp client. Return a C{Deferred} that
        fires when the server returns a result. Note that the C{Deferred} will
        callback even if the server returns some kind of error.

        @param command: A string containing an sftp command.

        @return: A C{Deferred} that fires when the sftp server returns a
        result. The payload is the server's response string.
        r2   r>  )	r   Deferredr9  r6  
isinstancestrr4   r   r   r*   commandr+   r+   r,   
runCommandD  s   


zSFTPTestProcess.runCommandc                    s(   t d fdd|D }t |S )ax  
        Run each command in sequence and return a Deferred that fires when all
        commands are completed.

        @param commands: A list of strings containing sftp commands.

        @return: A C{Deferred} that fires when all commands are completed. The
        payload is a list of response strings from the server, in the same
        order as the commands.
        r   c                    s   g | ]	}  j|qS r+   )runrN  ).0rM  r*   semr+   r,   
<listcomp>b  s    z-SFTPTestProcess.runScript.<locals>.<listcomp>)r   DeferredSemaphoregatherResults)r*   commandsdlr+   rQ  r,   	runScriptV  s   

zSFTPTestProcess.runScriptc                 C   s,   | j rtdS t | _| jd | jS )z
        Kill the process if it is still running.

        If the process is still running, sends a KILL signal to the transport
        and returns a C{Deferred} which fires when L{processEnded} is called.

        @return: a C{Deferred}.
        NKILL)r:  r   r   rI  r8  r   signalProcessr)   r+   r+   r,   killProcesse  s
   	

zSFTPTestProcess.killProcessc                 C   s,   d| _ | jr| jd}| _|d dS dS )zF
        Called by Twisted when the cftp client process ends.
        TN)r:  r8  r@  )r*   reasonr   r+   r+   r,   processEndedt  s
   zSFTPTestProcess.processEndedN)r;   r<   r=   r>   rt   r6  rC  rA  rG  rH  rN  rX  r[  r]  r+   r+   r+   r,   r5    s    
r5  c                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )CFTPClientTestBasec                 C   s   t dd}|tj W d    n1 sw   Y  t dd}|tj W d    n1 s1w   Y  tdd t dd}|dtj  W d    n1 sTw   Y  t| S )Nrsa_test.pubr   rsa_testi  kh_tests
   127.0.0.1 )	r   r   r   publicRSA_opensshprivateRSA_opensshrE   chmodr	   r-   r*   fr+   r+   r,   r-     s   
zCFTPClientTestBase.setUpc                 C   sF   t | j}t|}|t  t }||_tj	d|dd| _
d S )Nr   z	127.0.0.1)	interface)r.  r/  r
   PortalregisterCheckerr   conchTestPublicKeyCheckerConchTestServerFactoryr   	listenTCPserver)r*   realmpfacr+   r+   r,   startServer  s   

zCFTPClientTestBase.startServerc                 C   sH   t | jjds| d S d| jjj_t| jjjjj	}|
| j |S )Nprotor   )hasattrrm  factory_cbStopServerrr  expectedLoseConnectionr   maybeDeferredr   loseConnectionr   r   r+   r+   r,   
stopServer  s   
zCFTPClientTestBase.stopServerc                 C   s   t | jjS r$   )r   rw  rm  stopListeningr*   ignoredr+   r+   r,   ru    s   z CFTPClientTestBase._cbStopServerc              	   C   s4   dD ]}zt | W q ty   Y qw t| S )N)r_  r`  ra  )rE   removeBaseExceptionr	   tearDownre  r+   r+   r,   r    s   
zCFTPClientTestBase.tearDownN)r;   r<   r=   r-   rq  ry  ru  r  r+   r+   r+   r,   r^  ~  s    
r^  c                   @   s   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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 ).OurServerCmdLineClientTestsz
    Functional tests which launch a SFTP server over TCP on localhost and check
    cftp command line interface using a spawned process.

    Due to the spawned process you can not add a debugger breakpoint for the
    client code.
    c           
         s0  t      d} j j}tj||  dd}t	
dtj d|  t }t| _| fdd tj }tjtj|d< g }i }|D ]}t|trZ|d	}|| qN|D ]}|| }	t|trr|d	}t|	tr||	d	}	|	||< qbt	
| t	
| tj jtj||d
 |S )Nz-p %i -l testuser --known-hosts kh_test --user-authentications publickey --host-key-algorithms ssh-rsa -i rsa_test -a -v 127.0.0.1r   modrunning r   c                    
    j  S r$   )processProtocolr6  _r)   r+   r,   r0       
 z3OurServerCmdLineClientTests.setUp.<locals>.<lambda>
PYTHONPATHr2   env)r^  r-   rq  rm  getHostportr   	_makeArgsr   r   r?  r   r   r   rI  r5  r  r   rE   rF   copypathsepr  r}   rJ  rK  r4   r   r   spawnProcess)
r*   cmdsr  r   r  encodedCmds
encodedEnvcmdvarvalr+   r)   r,   r-     s>   












z!OurServerCmdLineClientTests.setUpc                    s      }| fdd |S )Nc                    r  r$   )r  r[  r  r)   r+   r,   r0    r  z6OurServerCmdLineClientTests.tearDown.<locals>.<lambda>)ry  r   r   r+   r)   r,   r    s   z$OurServerCmdLineClientTests.tearDownc                 C   s,   z
| j jd W d S  tjy   Y d S w )NrY  )r  r   rZ  r   ProcessExitedAlreadyr{  r+   r+   r,   _killProcess  s
   z(OurServerCmdLineClientTests._killProcessc                 C      | j |S )z
        Run the given command with the cftp client. Return a C{Deferred} that
        fires when the command is complete. Payload is the server's output for
        that command.
        )r  rN  rL  r+   r+   r,   rN       z&OurServerCmdLineClientTests.runCommandc                 G   r  )z
        Run the given commands with the cftp client. Returns a C{Deferred}
        that fires when the commands are all complete. The C{Deferred}'s
        payload is a list of output for each command.
        )r  rX  )r*   rV  r+   r+   r,   rX    r  z%OurServerCmdLineClientTests.runScriptc                 C   sL   | j }| ddddd}dd }|| || j|jt d|jg |S )z
        Test that 'pwd' reports the current remote directory, that 'lpwd'
        reports the current local directory, and that changing to a
        subdirectory then changing to its parent leaves you in the original
        remote directory.
        pwdlpwdzcd testDirectorycd ..c                 S   sD   g }| D ]}t |tr|d}|| q|dd |dd  S )zH
            Callback function for handling command output.
            r2   N      )rJ  bytesr   r   )r  r  r  r+   r+   r,   	cmdOutput  s   

z8OurServerCmdLineClientTests.testCdPwd.<locals>.cmdOutputr   )r/  rX  r   r6   r}   rE   getcwd)r*   homeDirr   r  r+   r+   r,   	testCdPwd  s   
z%OurServerCmdLineClientTests.testCdPwdc                    s&    fdd}  dddd}||S )z
        Check that 'ls -l' output includes the access permissions and that
        this output changes appropriately with 'chmod'.
        c                    sZ        | d d  | d d  | d d| d   | d d d S )Nr   s
   -rw-r--r--r   r   r   s
   ----------r  )flushLoggedErrorsr/   rD  r6   resultsr)   r+   r,   _check  s
   z7OurServerCmdLineClientTests.testChAttrs.<locals>._checkzls -l testfile1zchmod 0 testfile1zchmod 644 testfile1rX  r   r*   r  r   r+   r)   r,   testChAttrs  s   
z'OurServerCmdLineClientTests.testChAttrsc                    s@    fdd}  dd j  ddd}|dd	  ||S )
z
        Check 'ls' works as expected. Checks for wildcards, hidden files,
        listing directories and listing empty directories.
        c                    sf     | d g d   | d g d   | d ddg   | d g d   | d	 d
g d S )Nr   s   testDirectory   testRemoveFile   testRenameFiles	   testfile1r   r   r  r  r  )s   .testHiddenFiler  r  r  r   r6   r  r)   r+   r,   r  *  s   z4OurServerCmdLineClientTests.testList.<locals>._checkr   zls ../zls *Filezls -a *Filezls -l testDirectoryc                 S   s   dd | D S )Nc                 S   s   g | ]}| d qS )r>  )r   )rP  xr+   r+   r,   rS  @      zJOurServerCmdLineClientTests.testList.<locals>.<lambda>.<locals>.<listcomp>r+   )xsr+   r+   r,   r0  @  s    z6OurServerCmdLineClientTests.testList.<locals>.<lambda>)rX  r/  r  r   r  r+   r)   r,   testList$  s   
z$OurServerCmdLineClientTests.testListc                 C   sD   |  d}tdd }t|tr|d}|| j	| |S )zB
        Check that running the '?' command returns help.
        ?Nr   r2   )
rN  r   r   cmd_HELPr   rJ  rK  r4   r   r6   )r*   r   helpTextr+   r+   r,   testHelpC  s   


z$OurServerCmdLineClientTests.testHelpNc                 C   s   |  | | | dS )zg
        Assert that the files at C{name1} and C{name2} contain exactly the
        same data.
        N)r6   
getContent)r*   name1name2r?  r+   r+   r,   assertFilesEqualO  s   z,OurServerCmdLineClientTests.assertFilesEqualc                    sl   d jjjj t tr d  fdd}djj d}|| |fdd |S )	z
        Test that 'get' saves the remote file to the correct local location,
        that the output of 'get' is correct and that 'rm' actually removes
        the file.
        z)Transferred {}/testfile1 to {}/test file2r2   c                    s8    |   jdjdd dS )N	testfile1
test file2z
get failedzrm "test file2")r/   endswithr  r/  childrN  r   r  r*   r+   r,   	_checkGetd  s   


z6OurServerCmdLineClientTests.testGet.<locals>._checkGetzget testfile1 "z/test file2"c                          jd S )Nr  assertFalser/  r  existsr  r)   r+   r,   r0  p  r  z5OurServerCmdLineClientTests.testGet.<locals>.<lambda>)r,  r/  r}   rJ  rK  r4   rN  r   )r*   r  r   r+   r  r,   testGetV  s   

	

z#OurServerCmdLineClientTests.testGetc                    s     fdd}  d}||S )zQ
        Test that 'get' works correctly when given wildcard parameters.
        c                    s8      jdtdd    jdtdd d S )NtestRemoveFiletestRemoveFile get failedtestRenameFiletestRenameFile get failed)r  r/  r  r   )r|  r)   r+   r,   r  y  s   

z;OurServerCmdLineClientTests.testWildcardGet.<locals>._checkz
get testR*)rN  r   r  r+   r)   r,   testWildcardGett  s   

z+OurServerCmdLineClientTests.testWildcardGetc                    sh   dj  j d j  j d   fdd}dj j d}|| |fdd	 |S )
z
        Check that 'put' uploads files correctly and that they can be
        successfully removed. Also check the output of the put command.
        s   Transferred s   /testfile1 to s   /test"file2c                    s6    jdjd |   dS )Nr  
test"file2zrm "test\"file2")r  r/  r  r/   r  rN  r  r  r+   r,   	_checkPut  s
   
z6OurServerCmdLineClientTests.testPut.<locals>._checkPutput z/testfile1 "test\"file2"c                    r  )Nr  r  r  r)   r+   r,   r0    r  z5OurServerCmdLineClientTests.testPut.<locals>.<lambda>)r/  asBytesModer}   rN  r   )r*   r  r   r+   r  r,   testPut  s"   



z#OurServerCmdLineClientTests.testPutc                    s    j djdd}|d W d   n1 sw   Y   j djdd}|d W d   n1 s9w   Y   fdd	} d
 j j d}|| |S )zb
        Check that 'put' uploads files correctly when overwriting a longer
        file.
        shorterFilewmode   aN
longerFile   bbc                    s       jd jd d S )Nr  r  )r  r/  r  r  r)   r+   r,   r    s   zEOurServerCmdLineClientTests.test_putOverLongerFile.<locals>._checkPutr  z/shorterFile longerFile)r/  r  r   r   rN  r}   r   r*   rf  r  r   r+   r)   r,   test_putOverLongerFile  s   
z2OurServerCmdLineClientTests.test_putOverLongerFilec                    s    j d  djdd}|d W d   n1 s#w   Y   j djdd}|d W d   n1 sBw   Y   fdd	} d
 j j d}|| |S )z
        Check that 'put' uploads files correctly when overwriting a longer
        file and you use a wildcard to specify the files to upload.
        dirr   r  r  r  Nr  c                    s     d jd d S )Nr   )r  r  r/  r  r*   someDirr+   r,   r    s   zMOurServerCmdLineClientTests.test_putMultipleOverLongerFile.<locals>._checkPutr  z/dir/*)r/  r  createDirectoryr   r   rN  r}   r   r  r+   r  r,   test_putMultipleOverLongerFile  s   
z:OurServerCmdLineClientTests.test_putMultipleOverLongerFilec                    s>    fdd}  dd jj dd j  }|| |S )z
        What happens if you issue a 'put' command and include a wildcard (i.e.
        '*') in parameter? Check that all files matching the wildcard are
        uploaded to the correct directory.
        c                    sh     | d d   | d d   jd j dd   jd j dd d S )Nr   r   r   r  r  r  r  )r6   r  r/  r  r%  r  r)   r+   r,   check  s   

z:OurServerCmdLineClientTests.testWildcardPut.<locals>.checkr  r  z/testR*zcd %s)rX  r/  r}   r  r   )r*   r  r   r+   r)   r,   testWildcardPut  s   
z+OurServerCmdLineClientTests.testWildcardPutc                    4    fdd}  dd}|| | jd |S )z
        Test that 'ln' creates a file which appears as a link in the output of
        'ls'. Check that removing the new file succeeds without output.
        c                    s8        | d d  | d dd  dS )Nr   r   r      lzlink failedzrm testLink)r  r6   r/   rD  rN  r  r)   r+   r,   r    s   
z4OurServerCmdLineClientTests.testLink.<locals>._checkzln testLink testfile1zls -l testLinkr   rX  r   r6   r  r+   r)   r,   testLink  s
   
z$OurServerCmdLineClientTests.testLinkc                    r  )zV
        Test that we can create and remove directories with the cftp client.
        c                    s.     | d d  | d d  dS )Nr   r   r      dzrmdir testMakeDirectory)r6   r/   rD  rN  r  r)   r+   r,   r     s   
z?OurServerCmdLineClientTests.testRemoteDirectory.<locals>._checkmkdir testMakeDirectoryzls -l testMakeDirector?r   r  r  r+   r)   r,   testRemoteDirectory  
   
z/OurServerCmdLineClientTests.testRemoteDirectoryc                    s&    fdd}  dd}|| |S )z
        Test that a C{mkdir} on an existing directory fails with the
        appropriate error, and doesn't log an useless error server side.
        c                    s$     | d d   | d d d S )Nr   r   r   s   remote error 11: mkdir failedr  r  r)   r+   r,   r    s   zHOurServerCmdLineClientTests.test_existingRemoteDirectory.<locals>._checkr  r  r  r+   r)   r,   test_existingRemoteDirectory
  s   
z8OurServerCmdLineClientTests.test_existingRemoteDirectoryc                    sH     d jj d}| jd | fdd | jd |S )z
        Test that we can create a directory locally and remove it with the
        cftp client. This test works because the 'remote' server is running
        out of a local directory.
        zlmkdir z/testLocalDirectoryr   c                    s
     dS )Nzrmdir testLocalDirectory)rN  r  r)   r+   r,   r0     r  z@OurServerCmdLineClientTests.testLocalDirectory.<locals>.<lambda>)rN  r/  r}   r   r6   r   r+   r)   r,   testLocalDirectory  s
   z.OurServerCmdLineClientTests.testLocalDirectoryc                    r  )z1
        Test that we can rename a file.
        c                    s*     | d d   | d d  dS )Nr   r   r   s	   testfile2zrename testfile2 testfile1)r6   rN  r  r)   r+   r,   r  )  s   
z6OurServerCmdLineClientTests.testRename.<locals>._checkzrename testfile1 testfile2zls testfile?r   r  r  r+   r)   r,   
testRename$  r  z&OurServerCmdLineClientTests.testRenamer$   )r;   r<   r=   r>   r-   r  r  rN  rX  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r+   r+   r+   r,   r    s.    *
r  c                   @   s@   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S )OurServerBatchFileTestszm
    Functional tests which launch a SFTP server over localhost and checks csftp
    in batch interface.
    c                 C   s   t |  |   d S r$   r^  r-   rq  r)   r+   r+   r,   r-   ;  s   
zOurServerBatchFileTests.setUpc                 C      t |  |  S r$   )r^  r  ry  r)   r+   r+   r,   r  ?     
z OurServerBatchFileTests.tearDownc                    s   |    t d}|| W d    n1 sw   Y  | j j}d| f }tj| dddd  }t	
dtj d|  tj }tjtj|d< d| jj_ttj||d	} fd
d}|dd  || |S )Nr  z-p %i -l testuser --known-hosts kh_test --user-authentications publickey --host-key-algorithms ssh-rsa -i rsa_test -a -v -b %s 127.0.0.1r   r  r   r  r   r  r  c                    s   t   | S r$   )rE   r}  resfnr+   r,   _cleanupZ  s   
z9OurServerBatchFileTests._getBatchOutput.<locals>._cleanupc                 S   s   | d S )Nr   r+   r  r+   r+   r,   r0  ^  s    z9OurServerBatchFileTests._getBatchOutput.<locals>.<lambda>)r   r   r   rm  r  r  r   r  r   r   r?  r   r   rE   rF   r  r  r  r}   rt  rv  r   r   addBoth)r*   rf  fpr  r  r  r   r  r+   r  r,   _getBatchOutputC  s$   	


z'OurServerBatchFileTests._getBatchOutputc                    (   d} fdd}  |}|| |S )z
        Test whether batch file function of cftp ('cftp -b batchfile').
        This works by treating the file as a list of commands to be run.
        zpwd
ls
exit
c                    sP   |  d} tdt|     j j| d   | dd g d d S )Nr>  zRES %sr   r  r  )	r   r   r?  reprassertInr/  r  r}   r6   r  r)   r+   r,   _cbCheckResultm  s   

z=OurServerBatchFileTests.testBatchFile.<locals>._cbCheckResultr  r   r*   r  r  r   r+   r)   r,   testBatchFilec  s
   
	
z%OurServerBatchFileTests.testBatchFilec                    r  )zO
        Test that an error in the batch file stops running the batch.
        zchown 0 missingFile
pwd
exit
c                          j j|  d S r$   )assertNotInr/  r  r}   r  r)   r+   r,   r       z9OurServerBatchFileTests.testError.<locals>._cbCheckResultr  r   r+   r)   r,   	testErrorz  s
   

z!OurServerBatchFileTests.testErrorc                    r  )z_
        Test that a minus sign '-' at the front of a line ignores
        any errors.
        z-chown 0 missingFile
pwd
exit
c                    r  r$   )r  r/  r  r}   r  r)   r+   r,   r    r  z@OurServerBatchFileTests.testIgnoredError.<locals>._cbCheckResultr  r   r+   r)   r,   testIgnoredError  s
   

z(OurServerBatchFileTests.testIgnoredErrorN)
r;   r<   r=   r>   r-   r  r  r  r  r  r+   r+   r+   r,   r  4  s     r  sshz$no ssh command-line client availablesftpz%no sftp command-line client availablec                   @   rx   )	OurServerSftpClientTestsz@
    Test the sftp server against sftp command line client.
    c                 C   r  r$   r  r)   r+   r+   r,   r-     r  zOurServerSftpClientTests.setUpc                 C   s   |   S r$   )ry  r)   r+   r+   r,   r    s   z!OurServerSftpClientTests.tearDownc           	         s   t tj} }t|d}|d W d   n1 sw   Y  j j}t	j
  fdd}t	d| djj_dd	d
dd
dd
dd
dd
d|f d|df}fdd}td||}||S )a  
        Test the return of extended attributes by the server: the sftp client
        should ignore them, but still be able to parse the response correctly.

        This test is mainly here to check that
        L{filetransfer.FILEXFER_ATTR_EXTENDED} has the correct value.
        r  z	ls .
exitNc                    s    | |}d|d< |S )Nr   ext_foor+   )r*   sr   )
oldGetAttrr+   r,   	_getAttrs  s   
zCOurServerSftpClientTests.test_extendedAttributes.<locals>._getAttrsr  Tz-Fz	/dev/nullz-ozIdentitiesOnly=yeszIdentityFile=rsa_testzUserKnownHostsFile=kh_testzHostKeyAlgorithms=ssh-rsazPort=%iz-bztestuser@127.0.0.1c                    s:     | d d| d d dD ]
} || d  qd S )Nr   r   r   asciir  )r6   r   r  )r   ir)   r+   r,   r    s   z?OurServerSftpClientTests.test_extendedAttributes.<locals>.checkr  )dictrE   rF   r   r   r   rm  r  r  r!   r  rI   rt  rv  r   r   )	r*   r  r  rf  r  r  argsr  r   r+   )r  r*   r,   test_extendedAttributes  s:   




z0OurServerSftpClientTests.test_extendedAttributesN)r;   r<   r=   r>   r-   r  r  r+   r+   r+   r,   r	    s
    r	  )Qr>   r   re   rK   rE   r   r   rC   ior   r   unittestr   zope.interfacer   twisted.conchr   twisted.conch.interfacesr   $twisted.conch.test.test_filetransferr   r	   twisted.credr
   twisted.internetr   r   r   r   r   twisted.internet.taskr   twisted.internet.testingr   twisted.internet.utilsr   twisted.pythonr   twisted.python.fakepwdr   twisted.python.filepathr   twisted.python.procutilsr   twisted.python.reflectr   twisted.trial.unittestr   r   unixtwisted.conch.scriptsr   twisted.conch.scripts.cftpr   twisted.conch.sshr   twisted.conch.ssh.connectionr   twisted.conch.testr   r   twisted.conch.test.test_conchr    r!   ImportError	skipTestsIReactorProcessr"   r?   rp   ry   r   r   r   r.  ProcessProtocolr5  r^  r  r  r	  r+   r+   r+   r,   <module>   s   ' #&2  u	{'   g