
    hY                    	   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKr SSKrSSK	r	SSKJrJr  SSKJr  SSKJrJrJrJr  SSKJrJrJrJrJr  SSKJrJr  SSKJrJ r J!r!  S	r"S
r#Sr$Sr%Sr&Sr'Sr(Sr)Sr*Sr+Sr,Sr-Sr.Sr/Sr0Sr1Sr2Sr3Sr4Sr5Sr6Sr7Sr8S r9S!r:S"r;S#r<S$r=S%r>S&r?S'r@S(rAS)rBS*rCS+rDS,rES-rFS.rGS/rHS0rIS1rJS2rKS3rLS4rMS5rNS6rOS7rPS8rQS9rRS:rSS;rTS<rUS=rVS>rWS?rXS@rYSArZSBr[SCr\SDr]SEr^0 \"SF_\#SG_\$SH_\%SI_\&SJ_\'SK_\(SL_\)SM_\*SN_\+SO_\,SPSQ/_\-SR_\.SS_\/ST_\0SU_\2SV_\1SW_0 \3SX_\4SY_\5SZ_\6S[_\7S\_\8S]_\9S^_\:S__\;S`_\<Sa_\=Sb_\>Sc_\?Sd_\@Se_\ASf_\BSg_\CSh_E0 \DSi_\ESj_\FSk_\GSl_\HSm_\ISn_\JSo_\KSp_\LSq_\MSr_\NSs_\OSt_\PSu_\QSv_\RSw_\SSx_\TSy_E\USz\VS{\WS|\XS}\ZS~\[S\YS\\S\]S\^S0
Er_Sr`Sra " S S\b5      rcS rdS re\R                  " S5      rgSS jrh " S S\b5      ri " S S\i5      rj " S S\i5      rk " S S\i5      rl " S S\i5      rm " S S\i5      rn " S S\i5      ro " S S\i5      rp " S S\i5      rq " S S\i5      rr " S S\i5      rs " S S\i5      rt " S S\b5      ru " S S\b5      rv " S S\i5      rw " S S\i5      rx " S S\i5      ryS rz/ SQr{\" \R                  5       " S S\R                  5      5       r~ " S S\R                  5      r " S S5      r\" \R                  5       " S S5      5       r " S S\GR                  5      r " S S\GR                  \GR
                  5      r " S S\GR                  5      r " S S\5      r " S S\5      r " S S\5      rS rSS jr\" \5       " S S5      5       r\" \5       " S S5      5       r " S S\5      r\" \5       " S S5      5       r\" \GR$                  5       " S S5      5       r " S S\5      r " S S\5      r " S S\u5      r " S S\u5      r " S S\u5      r " S S\u5      r " S S\u5      r " S S5      r " S S\R                  5      r " S S\R                  5      r\" \5       " S S\R                  5      5       rS rS rS rS r " S S\GRF                  5      r " S S\GR                  5      r " S S\R                  5      r " S S\5      r " S S\GR                  5      rS rg! \
 a    S=r	r GNf = f)z 
An FTP protocol implementation
    N)	Interfaceimplementer)	copyright)checkerscredentialserrorportal)deferr   
interfacesprotocolreactor)basicpolicies)failurefilepathlog100120125150z200.1z200.2z200.3z200.4202z211.1z211.2212213214215z220.1z220.2z221.1z221.2225z226.1z226.2227229z230.1z230.2250z257.1z257.2z331.1z331.2332350z421.1z421.2425426450451452500501z502.1z502.2z502.3503504522z530.1z530.2532z550.1z550.2z550.3z550.4z550.5z550.6z550.7551552553z110 MARK yyyy-mmmmz120 service ready in %s minutesz3125 Data connection already open, starting transferz4150 File status okay; about to open data connection.z200 Command OKz200 Type set to %s.z200 PORT OKz200 EPSV ALL OKz5202 Command not implemented, superfluous at this sitez211 System status replyz211-Features:z211 Endz212 %sz213 %sz214 help: %sz215 UNIX Type: L8z220 %sz220 Service readyz&221 Service closing control connectionz221 Goodbye.z1225 data connection open, no transfer in progressz226 Abort successfulz226 Transfer Complete.z227 Entering Passive Mode (%s).z,229 Entering Extended Passive Mode (|||%s|).z230 User logged in, proceedz2230 Anonymous login ok, access restrictions apply.z&250 Requested File Action Completed OKz257 "%s"z257 "%s" createdz331 Password required for %s.z8331 Guest login ok, type your email address as password.z332 Need account for login.z6350 Requested file action pending further information.z6421 Service not available, closing control connection.z9421 Too many users right now, try again in a few minutes.z425 Can't open data connection.z.426 Transfer aborted.  Data connection closed.z/450 Requested action aborted. File unavailable.z8451 Requested action aborted. Local error in processing.z3452 Requested action aborted. Insufficient storage.z500 Syntax error: %sz#501 syntax error in argument(s) %s.z 502 Command '%s' not implementedz 502 Option '%s' not implemented.z3502 PASV available only for IPv4 (use EPSV instead)z&503 Incorrect sequence of commands: %sz'504 Not implemented for parameter '%s'.z,522 Network protocol not supported, use (%s)z$530 Please login with USER and PASS.z!530 Sorry, Authentication failed.z%532 Need an account for storing filesz"550 %s: No such file or directory.z550 %s: Permission denied.z:550 Anonymous users are forbidden to change the filesystemz%550 Cannot rmd, %s is not a directoryz550 %s: File existsz550 %s: is a directoryz"550 Requested action not taken: %sz551 Page type unknownzC552 Requested file action aborted, exceeded file storage allocationz5553 Requested action not taken, file name not allowed      c                       \ rS rSrSrSrg)InvalidPath   zD
Internal exception used to signify an error during parsing a path.
 N)__name__
__module____qualname____firstlineno____doc____static_attributes__r5       \/root/1688_scrapy/alibaba-scraper/venv/lib/python3.13/site-packages/twisted/protocols/ftp.pyr3   r3      s    r<   r3   c                 2   UR                  S5      (       a  / nOU SS nUR                  S5       Hc  nUS:X  d  US:X  a  M  US:X  a$  U(       a  UR                  5         M0  [        X5      eSU;   d  SU;   a  [        X5      eUR	                  U5        Me     U$ )zb
Normalize a path, as represented by a list of strings each
representing one segment of the path.
/N. .. )
startswithsplitpopr3   append)cwdpathsegsss       r=   
toSegmentsrL      s    
 s1vZZ_8qBw$Y
!#,,QY#(c((KKN  Kr<   c                 R   U [         R                  :X  a  [        R                  " [	        U5      5      $ U [         R
                  :X  d  U [         R                  :X  a  [        R                  " [        U5      5      $ U [         R                  :X  a  [        R                  " [        U5      5      $ U [         R                  :X  a  [        R                  " [        U5      5      $ U [         R                  :X  a  [        R                  " [        U5      5      $ [        R                  " 5       $ )z7
Map C{OSError} and C{IOError} to standard FTP errors.
)errnoENOENTr
   failFileNotFoundErrorEACCESEPERMPermissionDeniedErrorENOTDIRIsNotADirectoryErrorEEXISTFileExistsErrorEISDIRIsADirectoryError)erI   s     r=   errnoToFailurer\      s     	ELLzz+D122	
ell	a5;;.zz/566	
emm	zz.t455	
ell	zz/$/00	
ell	zz+D122zz|r<   TESTc                     U (       d  gU S   n[         R                  " U5      n[        R                  SUS5      nX2:X  a  gg)a}  
Helper for checking if a FTPShell `segments` contains a wildcard Unix
expression.

Only filename globbing is supported.
This means that wildcards can only be presents in the last element of
`segments`.

@type  segments: C{list}
@param segments: List of path elements as used by the FTP server protocol.

@rtype: Boolean
@return: True if `segments` contains a globbing expression.
Fr]   r0   T)fnmatch	translate_testTranslationreplace)segmentsglobCandidateglobTranslationsnonGlobTranslationss       r=   _isGlobbingExpressionrh      sG      RLM((7*226=!L.r<   c                   $    \ rS rSrSrS rS rSrg)FTPCmdErrori  z%
Generic exception for FTP commands.
c                 >    [         R                  " U /UQ76   Xl        g N)	Exception__init__errorMessage)selfmsgs     r=   rn   FTPCmdError.__init__   s    4&#&r<   c                 B    [         U R                     U R                  -  $ )z1
Generate a FTP response message for this error.
)RESPONSE	errorCodero   rp   s    r=   responseFTPCmdError.response$  s     '$*;*;;;r<   )ro   N)r6   r7   r8   r9   r:   rn   rw   r;   r5   r<   r=   rj   rj     s     <r<   rj   c                       \ rS rSrSr\rSrg)rQ   i+  z@
Raised when trying to access a non existent file or directory.
r5   N)r6   r7   r8   r9   r:   FILE_NOT_FOUNDru   r;   r5   r<   r=   rQ   rQ   +  s     Ir<   rQ   c                       \ rS rSrSr\rSrg)AnonUserDeniedErrori3  zO
Raised when an anonymous user issues a command that will alter the
filesystem
r5   N)r6   r7   r8   r9   r:   ANON_USER_DENIEDru   r;   r5   r<   r=   r|   r|   3  s    
 !Ir<   r|   c                       \ rS rSrSr\rSrg)rT   i<  zO
Raised when access is attempted to a resource to which access is
not allowed.
r5   N)r6   r7   r8   r9   r:   PERMISSION_DENIEDru   r;   r5   r<   r=   rT   rT   <  s    
 "Ir<   rT   c                       \ rS rSrSr\rSrg)rV   iE  z=
Raised when RMD is called on a path that isn't a directory.
r5   N)r6   r7   r8   r9   r:   IS_NOT_A_DIRru   r;   r5   r<   r=   rV   rV   E       Ir<   rV   c                       \ rS rSrSr\rSrg)rX   iM  z9
Raised when attempted to override an existing resource.
r5   N)r6   r7   r8   r9   r:   FILE_EXISTSru   r;   r5   r<   r=   rX   rX   M       Ir<   rX   c                       \ rS rSrSr\rSrg)rZ   iU  z;
Raised when DELE is called on a path that is a directory.
r5   N)r6   r7   r8   r9   r:   IS_A_DIRru   r;   r5   r<   r=   rZ   rZ   U  s     Ir<   rZ   c                       \ rS rSrSr\rSrg)CmdSyntaxErrori]  z(
Raised when a command syntax is wrong.
r5   N)r6   r7   r8   r9   r:   
SYNTAX_ERRru   r;   r5   r<   r=   r   r   ]  s     Ir<   r   c                       \ rS rSrSr\rSrg)CmdArgSyntaxErrorie  zR
Raised when a command is called with wrong value or a wrong number of
arguments.
r5   N)r6   r7   r8   r9   r:   SYNTAX_ERR_IN_ARGSru   r;   r5   r<   r=   r   r   e  s    
 #Ir<   r   c                       \ rS rSrSr\rSrg)CmdNotImplementedErrorin  z>
Raised when an unimplemented command is given to the server.
r5   N)r6   r7   r8   r9   r:   CMD_NOT_IMPLMNTDru   r;   r5   r<   r=   r   r   n  s     !Ir<   r   c                       \ rS rSrSr\rSrg)CmdNotImplementedForArgErroriv  zY
Raised when the handling of a parameter for a command is not implemented by
the server.
r5   N)r6   r7   r8   r9   r:   CMD_NOT_IMPLMNTD_FOR_PARAMru   r;   r5   r<   r=   r   r   v  s    
 +Ir<   r   c                       \ rS rSrSr\rSrg)PASVIPv6NotImplementedErrori  z%
Raised when PASV is used with IPv6.
r5   N)r6   r7   r8   r9   r:   PASV_IPV6_NOT_IMPLEMENTEDru   r;   r5   r<   r=   r   r     s     *Ir<   r   c                       \ rS rSrSrg)FTPErrori  r5   Nr6   r7   r8   r9   r;   r5   r<   r=   r   r         r<   r   c                       \ rS rSrSrg)PortConnectionErrori  r5   Nr   r5   r<   r=   r   r     r   r<   r   c                       \ rS rSrSr\rSrg)BadCmdSequenceErrori  zK
Raised when a client sends a series of commands in an illogical sequence.
r5   N)r6   r7   r8   r9   r:   BAD_CMD_SEQru   r;   r5   r<   r=   r   r     r   r<   r   c                       \ rS rSrSr\rSrg)AuthorizationErrori  z*
Raised when client authentication fails.
r5   N)r6   r7   r8   r9   r:   AUTH_FAILUREru   r;   r5   r<   r=   r   r     r   r<   r   c                       \ rS rSrSr\rSrg)UnsupportedNetworkProtocolErrori  zB
Raised when the client requests an unsupported network protocol.
r5   N)r6   r7   r8   r9   r:   UNSUPPORTED_NETWORK_PROTOCOLru   r;   r5   r<   r=   r   r     s     -Ir<   r   c                 F    [         R                  " S[        U5      -  SS9  g )NzdebugDeferred(): %sTdebug)r   rq   str)rp   _s     r=   debugDeferredr     s    GG!CF*$7r<   )NJanFebMarAprMayJunJulAugSepOctNovDecc                       \ rS rSrSrSrSrSrSrS r	S r
S rS rS	 rS
 rS rS rS rS rS rS rS rS rS rSrg)DTPi  FNlatin-1c                 j    SU l         U R                  R                  R                  S 5        / U l        g NT)isConnectedfactorydeferredcallback_bufferrv   s    r=   connectionMadeDTP.connectionMade  s)    &&t,r<   c                 d    SU l         U R                  b  U R                  R                  S 5        g g NF)r   _onConnLostr   rp   reasons     r=   connectionLostDTP.connectionLost  s/     '%%d+ (r<   c                 @    U R                   R                  US-   5        g)zV
Send a line to data channel.

@param line: The line to be sent.
@type line: L{bytes}
s   
N	transportwriterp   lines     r=   sendLineDTP.sendLine  s     	TG^,r<   c	                     S n	Sn
U
U=(       a    S=(       d    SUR                  5       UUSS USS UU	" [        R                  " U5      5      S.-  R                  U R                  5      nX-   $ )a  
Helper method to format one entry's info into a text entry like:
'drwxrwxrwx   0 user   group   0 Jan 01  1970 filename.txt'

@param name: C{bytes} name of the entry (file or directory or link)
@param size: C{int} size of the entry
@param directory: evals to C{bool} - whether the entry is a directory
@param permissions: L{twisted.python.filepath.Permissions} object
    representing that entry's permissions
@param hardlinks: C{int} number of hardlinks
@param modified: C{float} - entry's last modified time in seconds
    since the epoch
@param owner: C{str} username of the owner
@param group: C{str} group name of the owner

@return: C{str} in the requisite format
c                     [         R                  " 5       n[        U R                     U R                  U R
                  U R                  U R                  S.nUR
                  U R
                  :w  a  SU-  $ SU-  $ )N)monthdayyearhourminutez%(month)s %(day)02d %(year)5dz+%(month)s %(day)02d %(hour)02d:%(minute)02d)timegmtime_monthstm_montm_mdaytm_yeartm_hourtm_min)mtimenowinfos      r=   
formatDate.DTP._formatOneListResponse.<locals>.formatDate  sd    ++-C .}},,D {{emm+6==DtKKr<   zY%(directory)s%(permissions)s%(hardlinks)4d %(owner)-9s %(group)-9s %(size)15d %(date)12s d-N   )	directorypermissions	hardlinksownergroupsizedate)	shorthandr   r   encode	_encoding)rp   namer   r   r   r   modifiedr   r   r   formatrq   s               r=   _formatOneListResponseDTP._formatOneListResponse  s    *	L= 	 &.35#*446&rr"4;;x#89	 &
  	 zr<   c                 H    U R                  U R                  " U/UQ76 5        g rl   )r   r   )rp   r   rw   s      r=   sendListResponseDTP.sendListResponse  s    d11$BBCr<   c                 8    U R                   R                  X5      $ rl   r   registerProducerrp   producer	streamings      r=   r   DTP.registerProducer  s    ~~..xCCr<   c                 l    U R                   R                  5         U R                   R                  5         g rl   )r   unregisterProducerloseConnectionrv   s    r=   r  DTP.unregisterProducer  s"    ))+%%'r<   c                 p    U R                   (       a  U R                  R                  U5      $ [        S5      e)NzCrap damn crap damn crap damn)r   r   r   rm   rp   datas     r=   r   	DTP.write  s,    >>''--788r<   c                      U R                   R                  U5        g ! [         a    U R                  R	                  5          g f = frl   )_consr   BaseExceptionr   errbackrp   bytess     r=   
_conswriteDTP._conswrite"  s:    	'JJU# 	'$$&	's    $AAc                 x    U R                   b  U R                  U5        g U R                  R                  U5        g rl   )r  r  r   rG   r  s     r=   dataReceivedDTP.dataReceived(  s*    ::!OOE"LL&r<   c                 L    U R                   R                  5         S U l         U ?U$ rl   )r  r  r   rp   ignoreds     r=   _unregConsumerDTP._unregConsumer.  s$    

%%'
r<   c                    U R                   b   eXl         U R                   R                  U S5        U R                   H  nU R                  U5        M     S U l        U R                  (       a9  [
        R                  " 5       =U l        nUR                  U R                  5        U$ U R                   R                  5         S U l         [
        R                  " S 5      $ r   )r  r   r   r  r   r
   Deferredr   addBothr  r  succeed)rp   conschunkr   s       r=   registerConsumerDTP.registerConsumer4  s    zz!!!


##D$/\\EOOE" "#(>>#33DqIId))*HJJ))+DJ==&&r<   c                 8    U R                   R                  5         g rl   )r   resumeProducingrv   s    r=   r$  DTP.resumeProducingD  s    &&(r<   c                 8    U R                   R                  5         g rl   )r   pauseProducingrv   s    r=   r'  DTP.pauseProducingG      %%'r<   c                 8    U R                   R                  5         g rl   )r   stopProducingrv   s    r=   r+  DTP.stopProducingJ  s    $$&r<   )r   r  r   r   )r6   r7   r8   r9   r   r  r   r   r   r   r   r   r   r   r   r  r   r  r  r  r!  r$  r'  r+  r;   r5   r<   r=   r   r     si    KEKGI
,
-4lDD(9''' )('r<   r   c                   x    \ rS rSrSr\" 5       r\" 5       r\" 5       r\r	Sr
SS jrS rS rS rS	 rS
 rS rSrg)
DTPFactoryiN  a  
Client factory for I{data transfer process} protocols.

@ivar peerCheck: perform checks to make sure the ftp-pi's peer is the same
    as the dtp's
@ivar pi: a reference to this factory's protocol interpreter

@ivar _state: Indicates the current state of the DTPFactory.  Initially,
    this is L{_IN_PROGRESS}.  If the connection fails or times out, it is
    L{_FAILED}.  If the connection succeeds before the timeout, it is
    L{_FINISHED}.

@cvar _IN_PROGRESS: Token to signal that connection is active.
@type _IN_PROGRESS: L{object}.

@cvar _FAILED: Token to signal that connection has failed.
@type _FAILED: L{object}.

@cvar _FINISHED: Token to signal that connection was successfully closed.
@type _FINISHED: L{object}.
FNc                 |    Xl         X l        [        R                  " 5       U l        SU l        Uc  SSKJn  X0l        g)z
Constructor

@param pi: this factory's protocol interpreter
@param peerHost: if peerCheck is True, this is the tuple that the
    generated instance will use to perform security checks
Nr   r   )	pipeerHostr
   r  r   delayedCalltwisted.internetr   _reactor)rp   r1  r2  r   s       r=   rn   DTPFactory.__init__o  s1      (?0r<   c                    [         R                  " SSS9  U R                  U R                  La  g U R                  U l        U R                  5         [        5       nXl        U R                  Ul        X R                  l	        U$ )NzDTPFactory.buildProtocolTr   )
r   rq   _state_IN_PROGRESS	_FINISHEDcancelTimeoutr   r   r1  dtpInstancerp   addrps      r=   buildProtocolDTPFactory.buildProtocol  sc    *$7;;d///nnE	wwr<   c                 N    [         R                  " SSS9  U R                  5         g )NzdtpFactory.stopFactoryTr   )r   rq   r;  rv   s    r=   stopFactoryDTPFactory.stopFactory  s    (5r<   c                    [         R                  " S5        U R                  U R                  La  g U R                  U l        U R
                  nS U l        UR                  [        [        R                  " S5      5      5        g )Nz$timed out waiting for DTP connectionzDTPFactory timeout)
r   rq   r8  r9  _FAILEDr   r  r   r
   TimeoutError)rp   r   s     r=   timeoutFactoryDTPFactory.timeoutFactory  s]    67;;d///llMM			%e&8&89M&NOPr<   c                     U R                   bP  U R                   R                  5       (       a0  [        R                  " SSS9  U R                   R	                  5         g g g )Nzcancelling DTP timeoutTr   )r3  activer   rq   cancelrv   s    r=   r;  DTPFactory.cancelTimeout  sL    'D,<,<,C,C,E,EGG,D9##% -F'r<   c                     [         R                  " SU-  5        U R                  R                  XR                  5      U l        g )Nz'DTPFactory.setTimeout set to %s seconds)r   rq   r5  	callLaterrH  r3  )rp   secondss     r=   
setTimeoutDTPFactory.setTimeout  s1    9GCD==227<O<OPr<   c                     U R                   U R                  La  g U R                  U l         U R                  nS U l        UR	                  [        U5      5        g rl   )r8  r9  rF  r   r  r   )rp   	connectorr   r   s       r=   clientConnectionFailed!DTPFactory.clientConnectionFailed  sD    ;;d///llMM			%f-.r<   )r5  r8  r   r3  r2  r1  )NN)r6   r7   r8   r9   r:   objectr9  rF  r:  r8  	peerCheckrn   r@  rC  rH  r;  rQ  rU  r;   r5   r<   r=   r.  r.  N  sO    , 8LhGIF I "Q&
Q/r<   r.  c                        \ rS rSrS rS rSrg)ASCIIConsumerWrapperi  c                    Xl         UR                  U l        UR                  U l        [        R                  S:X  d$  [        [        R                  5      S:X  d   S5       e[        R                  S:X  a  UR                  U l        g g )N
r0   z6Unsupported platform (yea right like this even exists))r  r   r  oslineseplenr   )rp   r  s     r=   rn   ASCIIConsumerWrapper.__init__  sp    	 $ 5 5"&"9"9 JJ& C

Oq$8	DC	D8 ::DJ  r<   c                 t    U R                   R                  UR                  [        R                  S5      5      $ )Nr\  )r  r   rc   r]  r^  r  s     r=   r   ASCIIConsumerWrapper.write  s$    yyu}}RZZ@AAr<   )r  r   r  r   N)r6   r7   r8   r9   rn   r   r;   r5   r<   r=   rZ  rZ    s    
$Br<   rZ  c                   0    \ rS rSrSrS rS rS rS rSr	g)	FileConsumeri  z
A consumer for FTP input that writes data to a file.

@ivar fObj: a file object opened for writing, used to write data received.
@type fObj: C{file}
c                     Xl         g rl   )fObjrp   rf  s     r=   rn   FileConsumer.__init__  s    	r<   c                 "    Xl         U(       d   eg rl   )r   r   s      r=   r   FileConsumer.registerProducer  s     yr<   c                 F    S U l         U R                  R                  5         g rl   )r   rf  closerv   s    r=   r  FileConsumer.unregisterProducer  s    		r<   c                 :    U R                   R                  U5        g rl   )rf  r   r  s     r=   r   FileConsumer.write  s    		r<   )rf  r   N)
r6   r7   r8   r9   r:   rn   r   r  r   r;   r5   r<   r=   rd  rd    s    r<   rd  c                   "    \ rS rSrSrSrS rSrg)FTPOverflowProtocoli  z:FTP mini-protocol for when there are too many connections.r   c                     U R                  [        [           R                  U R                  5      5        U R
                  R                  5         g rl   )r   rt   TOO_MANY_CONNECTIONSr   r   r   r  rv   s    r=   r   "FTPOverflowProtocol.connectionMade  s3    h34;;DNNKL%%'r<   r5   N)r6   r7   r8   r9   r:   r   r   r;   r5   r<   r=   rq  rq    s    DI(r<   rq  c                     ^  \ rS rSrSrSr\" S5      u  rrr	r
SrSrSrSrSrSrSrSr\\4rSS	/r/ S
Qr\" SS5      r\R4                  rSrS rU 4S jrS rS r S r!S r"S r#S9S jr$S r%S r&S r'S r(S9S jr)S r*S r+S r,S9S jr-S r.S  r/S! r0S" r1S# r2S$ r3S% r4S& r5S' r6S( r7S) r8S* r9S+ r:S, r;S- r<S. r=S/ r>S0 r?S1 r@S2 rAS3 rBS4 rCS5 rDS6 rES7 rFS8rGU =rH$ ):FTPi  a  
Protocol Interpreter for the File Transfer Protocol

@ivar state: The current server state.  One of L{UNAUTH},
    L{INAUTH}, L{AUTHED}, L{RENAMING}.

@ivar shell: The connected avatar
@ivar binary: The transfer mode.  If false, ASCII.
@ivar dtpFactory: Generates a single DTP for this session
@ivar dtpPort: Port returned from listenTCP
@ivar listenFactory: A callable with the signature of
    L{twisted.internet.interfaces.IReactorTCP.listenTCP} which will be used
    to create Ports for passive connections (mainly for testing).
@ivar _epsvAll: If true, "EPSV ALL" was received from the client,
    requiring the server to reject all data connection setup commands
    other than EPSV.  See RFC 2428.
@ivar _supportedNetworkProtocols: A collection of network protocol
    numbers supported by the EPRT and EPSV commands.

@ivar passivePortRange: iterator used as source of passive port numbers.
@type passivePortRange: C{iterator}

@cvar UNAUTH: Command channel is not yet authenticated.
@type UNAUTH: L{int}

@cvar INAUTH: Command channel is in the process of being authenticated.
@type INAUTH: L{int}

@cvar AUTHED: Command channel was successfully authenticated.
@type AUTHED: L{int}

@cvar RENAMING: Command channel is between the renaming command sequence.
@type RENAMING: L{int}
F   
   NTFEATQUIT)ry  MDTMPASVSIZEzTYPE A;Ir   r0   r   c                 >    [         U   U-  nU R                  U5        g rl   )rt   r   )rp   keyargsrq   s       r=   reply	FTP.reply   s    smd"cr<   c                    > [        U[        5      (       a  UR                  U R                  5      n[        TU ]  U5        g)zI
(Private) Encodes and sends a line

@param line: L{bytes} or L{unicode}
N)
isinstancer   r   r   superr   )rp   r   	__class__s     r=   r   FTP.sendLine$  s1     dC  ;;t~~.Dr<   c                     U R                   U l        U R                  U R                  5        U R	                  [
        U R                  R                  5        g rl   )UNAUTHstaterQ  timeOutr  WELCOME_MSGr   welcomeMessagerv   s    r=   r   FTP.connectionMade.  s5    [[
%

; ; ;<r<   c                 *   U R                   (       a  U R                  5         U R                  S 5        [        U R                  S5      (       a1  U R                  R
                  b  U R                  R                  5         S U l        SU l        S U l        g )NlogoutF)
dtpFactory
cleanupDTPrQ  hasattrshellr  _epsvAllr   r   s     r=   r   FTP.connectionLost3  sf     ??OO4::x((TZZ->->-JJJ
r<   c                 8    U R                   R                  5         g rl   r   r  rv   s    r=   timeoutConnectionFTP.timeoutConnection@  r)  r<   c                   ^ ^	 T R                  5         T R                  5         UR                  T R                  5      nU	U 4S jnU 4S jnU 4S jnUR	                  S5      nUS:w  a  US U m	XS-   S  4nOUm	Sn[
        R                  " T R                  T	/UQ76 nUR                  X25        UR                  [        R                  5        SS	KJn  UR                  " SUR                  U5        g )
Nc                   >^  T R                  [        5      (       a*  TR                  T R                  R	                  5       5        g T R                  [
        5      (       a4  [        U 4S jS 5       5      (       a  TR                  [        T S35        g [        R                  " S5        [        R                  " T 5        TR                  [        S5        g )Nc              3   \   >#    U  H!  nUTR                   R                  S    ;   v   M#     g7f)r   N)valuer  ).0rq   errs     r=   	<genexpr>:FTP.lineReceived.<locals>.processFailed.<locals>.<genexpr>K  s*      .LC syy~~a((Ls   ),)ztakes exactlyzrequired positional argumentz requires an argument.zUnexpected FTP errorzinternal server error)checkrj   r   r  rw   	TypeErroranyr  r   r   rq   r  REQ_ACTN_NOT_TAKEN)r  cmdrp   s   `r=   processFailed'FTP.lineReceived.<locals>.processFailedH  s    yy%%cii00239%%# .L. + + 

:#.D'EF./

-/FGr<   c                 z   > [        U [        5      (       a  TR                  " U 6   g U b  TR                  U 5        g g rl   )r  tupler  resultrp   s    r=   processSucceeded*FTP.lineReceived.<locals>.processSucceededU  s3    &%((

F##

6" $r<   c                 J   > TR                   (       d  TR                  5         g g rl   )disconnectedr$  )r  rp   s    r=   allDone!FTP.lineReceived.<locals>.allDone[  s    $$$$& %r<    r_   r0   r5   r   r0  )resetTimeoutr'  decoder   findr
   maybeDeferredprocessCommandaddCallbacks
addErrbackr   r  r4  r   rO  r  )
rp   r   r  r  r  
spaceIndexr  r   r   r  s
   `        @r=   lineReceivedFTP.lineReceivedC  s    {{4>>*	H	#	' YYs^
{
#Ca)*,DCD 3 3S@4@	'7	SWW
 	-!QYY0r<   c                   ^ ^ UU 4S jnUR                  5       nUT R                  ;   a  U" U5      $ T R                  T R                  :X  a)  US:X  a  T R                  " T6 $ US:X  a  [
        S4$ [        $ T R                  T R                  :X  a  US:X  a  T R                  " T6 $ [
        S4$ T R                  T R                  :X  a  U" U5      $ T R                  T R                  :X  a  US:X  a  T R                  " T6 $ [
        S4$ g )Nc                 r   > [        TSU -   S 5      nUb  U" T6 $ [        R                  " [        U 5      5      $ )Nftp_)getattrr
   rP   r   )commandmethodparamsrp   s     r=   call_ftp_command,FTP.processCommand.<locals>.call_ftp_commandr  s;    T6G#3T:F!v&::4W=>>r<   USERPASSzUSER required before PASSzPASS required after USERRNTOzRNTO required after RNFR)upperPUBLIC_COMMANDSr  r  ftp_USERr   NOT_LOGGED_ININAUTHftp_PASSAUTHEDRENAMINGftp_RNTO)rp   r  r  r  s   ` ` r=   r  FTP.processCommandq  s    	? iik$&&&#C((ZZ4;;&f}}}f--"$???$$ZZ4;;&f}}}f--"$>>>ZZ4;;&#C((ZZ4==(f}}}f--"$>>>	 )r<   c                     U R                    H  n U R                  X1US9nUs  $    [        R                  " SWSU R                    35      e! [        R                   a     MV  f = f)aN  
Return a port for passive access, using C{self.passivePortRange}
attribute.

@param factory: the protocol factory to connect to the port.
@type factory: L{twisted.internet.protocol.ServerFactory}

@param interface: the local IPv4 or IPv6 address to which to bind;
    defaults to "", i.e. all IPv4 addresses.
@type interface: C{str}
	interfacerA   zNo port available in range )passivePortRangelistenFactoryr   CannotListenError)rp   r   r  portndtpPorts        r=   
getDTPPortFTP.getDTPPort  sz     **E,,Uy,Q  + %%4T5J5J4KL
 	
	 ** s   AA$#A$c                    U(       d  [         R                  " [        S5      5      $ Xl        U R                  U l        U R                  R                  (       a*  U R                  U R                  R                  :X  a  [        $ [        U4$ )zK
First part of login.  Get the username the peer wants to
authenticate as.
zUSER requires an argument)r
   rP   r   _userr  r  r   allowAnonymoususerAnonymousGUEST_NAME_OK_NEED_EMAILUSR_NAME_OK_NEED_PASS)rp   usernames     r=   r  FTP.ftp_USER  s_    
 ::n-HIJJ
[[
<<&&4::9S9S+S++)844r<   c                   ^ ^ T R                   R                  (       a@  T R                  T R                   R                  :X  a  [        R
                  " 5       n[        mO'[        R                  " T R                  U5      n[        mT ?UU 4S jnU 4S jnT R                  R                  US[        5      nUR                  X45        U$ )zN
Second part of login.  Get the password the peer wants to
authenticate with.
c                 ~   > U u  pnU[         L d   S5       eUTl        UTl        / Tl        TR                  Tl        T$ )NzThe realm is busted, jerk.)	IFTPShellr  r  workingDirectoryr  r  )r  r  avatarr  r  rp   s       r=   _cbLoginFTP.ftp_PASS.<locals>._cbLogin  sG    *0'Y	)G+GG)DJ DK$&D!DJLr<   c                    > U R                   " [        R                  [        R                  5        TR                  Tl        [        erl   )trap
cred_errorUnauthorizedLoginUnhandledCredentialsr  r  r   )r   rp   s    r=   _ebLoginFTP.ftp_PASS.<locals>._ebLogin  s.    LL55z7V7VWDJ$$r<   N)r   r  r  r  r   	AnonymousGUEST_LOGGED_IN_PROCEEDUsernamePasswordUSR_LOGGED_IN_PROCEEDr	   loginr  r  )rp   passwordcredsr  r  r   r  s   `     @r=   r  FTP.ftp_PASS  s    
 <<&&4::9S9S+S))+E+E  00XFE)EJ		%
 KKeT95	x*r<   c                 @   U R                   (       a  [        R                  " [        S5      5      $ U R                  R                  5       R                  n [        R                  " U5      nUR                  b  [        UR                  5      nO[        R                  " [        5       5      $ U R                  b  U R                  5         [        U S9U l        U R                  R!                  U R"                  5        U R%                  U R                  5      U l        U R&                  R                  5       R(                  nU R+                  [,        [/        X5      5        U R                  R0                  R3                  S 5      $ ! [        R                   a     Nf = f)ad  
Request for a passive connection

from the rfc::

    This command requests the server-DTP to "listen" on a data port
    (which is not its default data port) and to wait for a connection
    rather than initiate one upon receipt of a transfer command.  The
    response to this command includes the host and port address this
    server is listening on.
z may not send PASV after EPSV ALLr1  c                     g rl   r5   igns    r=   <lambda>FTP.ftp_PASV.<locals>.<lambda>      r<   )r  r
   rP   r   r   getHosthost	ipaddressIPv6Addressipv4_mappedr   r   AddressValueErrorr  r  r.  rQ  
dtpTimeoutr  r  portr  ENTERING_PASV_MODEencodeHostPortr   addCallback)rp   r  addressr  s       r=   ftp_PASVFTP.ftp_PASV  s4    ==::12TUVV~~%%',,	A++D1G "". 7../ zz"="?@@ ??& OO$-""4??3t7||##%**

%~d'AB''334DEE7 ** 		s   F FFc                      [        U5      nXR                  ;  a+  [	        SR                  S U R                   5       5      5      eg! [         a    [        U5      ef = f)a:  
Validate the network protocol requested in an EPRT or EPSV command.

For now we just hardcode the protocols we support, since this layer
doesn't have a good way to discover that.

@param protocol: An address family number.  See RFC 2428 section 2.
@type protocol: L{str}

@raise FTPCmdError: If validation fails.
,c              3   8   #    U  H  n[        U5      v   M     g 7frl   )r   )r  r?  s     r=   r  /FTP._validateNetworkProtocol.<locals>.<genexpr>"  s     I)HAQ)Hs   N)int
ValueErrorr   _supportedNetworkProtocolsr   join)rp   r   s     r=   _validateNetworkProtocolFTP._validateNetworkProtocol  sd    	.8}H :::1I)H)HII  ;  	.#H--	.s   A Ac                 n   US:X  a  SU l         [        $ U(       a   U R                  U5        U R                  b  U R                  5         [        U S9U l        U R                  R                  U R                  5        U(       a
  U[        :X  a  SnOSnU R                  U R                  US9U l        U R                  R                  5       R                  nU R!                  ["        U5        U R                  R$                  R'                  S 5      $ ! [         a    [        R
                  " 5       s $ f = f)a  
Extended request for a passive connection.

As described by U{RFC 2428 section
3<https://tools.ietf.org/html/rfc2428#section-3>}::

    The EPSV command requests that a server listen on a data port
    and wait for a connection.  The EPSV command takes an optional
    argument.  The response to this command includes only the TCP
    port number of the listening connection.  The format of the
    response, however, is similar to the argument of the EPRT
    command.  This allows the same parsing routines to be used for
    both commands.  In addition, the format leaves a place holder
    for the network protocol and/or network address, which may be
    needed in the EPSV response in the future.
ALLTr  z::rA   r  c                     g rl   r5   r   s    r=   r  FTP.ftp_EPSV.<locals>.<lambda>N  r  r<   )r  EPSV_ALL_OKr  rj   r
   rP   r  r  r.  rQ  r  
_AFNUM_IP6r  r  r  r  r  ENTERING_EPSV_MODEr   r  )rp   r   r  r  s       r=   ftp_EPSVFTP.ftp_EPSV%  s    " u DM$--h7
 ??& OO$-""4??38z1IIt)L||##%**

%t,''334DEE%  $zz|#$s   D D43D4c                 v   U R                   (       a  [        R                  " [        S5      5      $ [	        [        [        UR                  S5      5      5      nS[	        US S 5      -  nUS   S-  US   -  nU R                  b  U R                  5         [        X R                  R                  5       R                  S9U l        U R                  R                  U R                  5        [         R"                  " X4U R                  5      U l        S nS	 nU R                  R&                  R)                  XV5      $ )
Nz may not send PORT after EPSV ALLr  z%d.%d.%d.%drw  r      r1  r2  c                     [         $ rl   ENTERING_PORT_MODEr  s    r=   	connectedFTP.ftp_PORT.<locals>.connected`      %%r<   c                 8    U R                  [        5        [        $ rl   r  r   CANT_OPEN_DATA_CNXr  s    r=   
connFailed FTP.ftp_PORT.<locals>.connFailedc      HH()%%r<   )r  r
   rP   r   r  mapr  rE   r  r  r.  r   getPeerr  rQ  r  r   
connectTCPr  r   r  )rp   r  r>  ipr  r-  r4  s          r=   ftp_PORTFTP.ftp_PORTP  s    ==::12TUVVSgmmC012U48_,Aw!|d1g% ??&OO$~~7M7M7O7T7TU""4??3))"DOOD	&	& ''44YKKr<   c                    U R                   (       a  [        R                  " [        S5      5      $  [	        U5      u  p#nU(       a   U R                  U5        U R                  b  U R                  5         [        X R                  R                  5       R                  S9U l	        U R                  R                  U R                   5        ["        R$                  " X4U R                  5      U l        S nS nU R                  R(                  R+                  XV5      $ ! [
         a"    [        R                  " [        U5      5      s $ f = f! [         a    [        R                  " 5       s $ f = f)a[  
Extended request for a data connection.

As described by U{RFC 2428 section
2<https://tools.ietf.org/html/rfc2428#section-2>}::

    The EPRT command allows for the specification of an extended
    address for the data connection.  The extended address MUST
    consist of the network protocol as well as the network and
    transport addresses.
z may not send EPRT after EPSV ALLr(  c                     [         $ rl   r*  r,  s    r=   r-  FTP.ftp_EPRT.<locals>.connected  r/  r<   c                 8    U R                  [        5        [        $ rl   r1  r3  s    r=   r4   FTP.ftp_EPRT.<locals>.connFailed  r6  r<   )r  r
   rP   r   decodeExtendedAddressr  r   r  rj   r  r  r.  r   r8  r  rQ  r  r   r9  r  r   r  )rp   extendedAddressr   r:  r  r-  r4  s          r=   ftp_EPRTFTP.ftp_EPRTi  s    ==::12TUVV	B!6!GH$ $--h7
 ??&OO$~~7M7M7O7T7TU""4??3))"DOOD	&	& ''44YKK/  	B::/@AA	B
  $zz|#$s#   D E )EEE-,E-c                 R    [        U[        5      (       a  UR                  S5      $ U$ )a=  
Encode C{name} to be sent over the wire.

This encodes L{unicode} objects as UTF-8 and leaves L{bytes} as-is.

As described by U{RFC 3659 section
2.2<https://tools.ietf.org/html/rfc3659#section-2.2>}::

    Various FTP commands take pathnames as arguments, or return
    pathnames in responses. When the MLST command is supported, as
    indicated in the response to the FEAT command, pathnames are to be
    transferred in one of the following two formats.

        pathname = utf-8-name / raw
        utf-8-name = <a UTF-8 encoded Unicode string>
        raw = <any string that is not a valid UTF-8 encoding>

    Which format is used is at the option of the user-PI or server-PI
    sending the pathname.

@param name: Name to be encoded.
@type name: L{bytes} or L{unicode}

@return: Wire format of C{name}.
@rtype: L{bytes}
zutf-8)r  r   r   )rp   r   s     r=   _encodeNameFTP._encodeName  s%    6 dC  ;;w''r<   c                   ^  T R                   b  T R                   R                  (       d  [        R                  " [	        S5      5      $ UR                  5       S;   a  SnU 4S jn [        T R                  U5      nT R                  R                  US5      nUR                  U5        U$ ! [         a"    [        R                  " [        U5      5      s $ f = f)az  This command causes a list to be sent from the server to the
passive DTP.  If the pathname specifies a directory or other
group of files, the server should transfer a list of files
in the specified directory.  If the pathname specifies a
file then the server should send current information on the
file.  A null argument implies the user's current working or
default directory.
"must send PORT or PASV before RETR)z-az-lz-laz-alrA   c                    > TR                  [        5        U  H1  u  pTR                  U5      nTR                  R	                  X5        M3     TR                  R
                  R                  5         [        4$ rl   )r  DATA_CNX_ALREADY_OPEN_START_XFRrG  r<  r   r   r  TXFR_COMPLETE_OK)resultsr   attrsrp   s      r=   
gotListing FTP.ftp_LIST.<locals>.gotListing  sc    JJ67&''-  11$>  ' &&557$&&r<   )r   r   r   r   r   r   r   )r<  r   r
   rP   r   lowerrL   r  r3   rQ   r  listr  )rp   rI   rP  rd   r   s   `    r=   ftp_LISTFTP.ftp_LIST  s     #4+;+;+G+G::12VWXX ::<55D	'	7!$"7"7>H JJOO
 	
j!!  	7::/566	7s   &B+ +)CCc                   ^  T R                   b  T R                   R                  (       d  [        R                  " [	        S5      5      $  [        T R                  U5      nU 4S jnU 4S jn[        U5      (       a  UR                  5       nOSnT R                  R                  U5      nUR                  X55        UR                  U5        U$ ! [         a"    [        R                  " [        U5      5      s $ f = f)a  
This command causes a directory listing to be sent from the server to
the client. The pathname should specify a directory or other
system-specific file group descriptor. An empty path implies the
current working directory. If the path is non-existent, send nothing.
If the path is to a file, send only the file name.

@type path: C{str}
@param path: The path for which a directory listing should be returned.

@rtype: L{Deferred}
@return: a L{Deferred} which will be fired when the listing request
    is finished.
NrJ  c                 L  > TR                  [        5        U  H^  u  p#U(       a&  U(       d  M  [        R                  " X!5      (       d  M2  TR                  U5      nTR                  R                  U5        M`     TR                  R                  R                  5         [        4$ )a5  
Send, line by line, each matching file in the directory listing,
and then close the connection.

@type results: A C{list} of C{tuple}. The first element of each
    C{tuple} is a C{str} and the second element is a C{list}.
@param results: The names of the files in the directory.

@param glob: A shell-style glob through which to filter results
    (see U{http://docs.python.org/2/library/fnmatch.html}), or
    L{None} for no filtering.
@type glob: L{str} or L{None}

@return: A C{tuple} containing the status code for a successful
    transfer.
@rtype: C{tuple}
)	r  rL  r`   rG  r<  r   r   r  rM  )rN  globr   r  rp   s       r=   cbListFTP.ftp_NLST.<locals>.cbList  sz    $ JJ67!()D)D++D1D$$--d3 ") &&557$&&r<   c                 Z   > TR                   R                  R                  5         [        4$ )a  
RFC 959 specifies that an NLST request may only return directory
listings. Thus, send nothing and just close the connection.

@type results: L{Failure}
@param results: The L{Failure} wrapping a L{FileNotFoundError} that
    occurred while trying to list the contents of a nonexistent
    directory.

@returns: A C{tuple} containing the status code for a successful
    transfer.
@rtype: C{tuple}
)r<  r   r  rM  )rN  rp   s    r=   listErrFTP.ftp_NLST.<locals>.listErr  s&     &&557$&&r<   )r<  r   r
   rP   r   rL   r  r3   rQ   rh   rF   r  rS  r  r  )rp   rI   rd   rY  r\  rX  r   s   `      r=   ftp_NLSTFTP.ftp_NLST  s      #4+;+;+G+G::12VWXX	7!$"7"7>H	'4	'" !** <<>DDJJOOH%	f#	Ws  	7::/566	7s   
C )C:9C:c                    ^ ^  [        T R                  U5      mUU 4S jnT R                  R                  T5      R                  U5      $ ! [         a"    [        R                  " [        U5      5      s $ f = f)Nc                     > TTl         [        4$ rl   )r  REQ_FILE_ACTN_COMPLETED_OK)r  rd   rp   s    r=   accessGranted"FTP.ftp_CWD.<locals>.accessGranted6  s    $,D!.00r<   )	rL   r  r3   r
   rP   rQ   r  accessr  )rp   rI   rc  rd   s   `  @r=   ftp_CWDFTP.ftp_CWD/  sg    	7!$"7"7>H
	1 zz  *66}EE  	7::/566	7s   A )A76A7c                 $    U R                  S5      $ )NrB   )rf  rv   s    r=   ftp_CDUPFTP.ftp_CDUP<  s    ||D!!r<   c                 J    [         SSR                  U R                  5      -   4$ )Nr?   )	PWD_REPLYr  r  rv   s    r=   ftp_PWDFTP.ftp_PWD?  s!    3$*?*?!@@AAr<   c                   ^ ^^^^	 T R                   c  [        S5      e [        T R                  U5      m	T R                  S5        U 4S jnT R                  (       d  [        T R                   5      mOT R                   mS mS mUUUU 4S jnU	4S jnT R                  R                  T	5      nUR                  X45        UR                  U5        U$ ! [         a"    [
        R                  " [        U5      5      s $ f = f)aX  
This command causes the content of a file to be sent over the data
transfer channel. If the path is to a folder, an error will be raised.

@type path: C{str}
@param path: The path to the file which should be transferred over the
data transfer channel.

@rtype: L{Deferred}
@return: a L{Deferred} which will be fired when the transfer is done.
Nz.PORT, PASV, EPRT, or EPSV required before RETRc                 R   > TR                  TR                  R                  5        U $ rl   rQ  r   r  r  s    r=   enableTimeout#FTP.ftp_RETR.<locals>.enableTimeout\      OODLL001Mr<   c                     [         4$ rl   rM  r  s    r=   cbSentFTP.ftp_RETR.<locals>.cbSentf  s    $&&r<   c                     [         R                  " S5        [         R                  " U 5        U R                  [        5      (       a  U $ [
        4$ )Nz7Unexpected error attempting to transmit file to client:)r   rq   r  r  rj   CNX_CLOSED_TXFR_ABORTEDr3  s    r=   ebSentFTP.ftp_RETR.<locals>.ebSenti  s7    GGMNGGCLyy%%
+--r<   c                    > TR                   R                  (       a  TR                  [        5        OTR                  [        5        U R                  T5      nUR                  TT5        U$ rl   )r<  r   r  rL  FILE_STATUS_OK_OPEN_DATA_CNXsendr  )filer   rx  r  r|  rp   s     r=   cbOpenedFTP.ftp_RETR.<locals>.cbOpenedp  sL    ++

:;

78		$ANN66*Hr<   c                 T  > U R                  [        [        [        5      (       d,  [        R
                  " S5        [        R                  " U 5        U R                  [        5      (       a'  U R                  R                  SR                  T5      4$ [        SR                  T5      4$ )Nz:Unexpected error attempting to open file for transmission:r?   )r  rT   rQ   rZ   r   rq   r  rj   r  ru   r  rz   r  newsegss    r=   ebOpenedFTP.ftp_RETR.<locals>.ebOpened{  sx    99%'8:K  WXyy%%		++SXXg->??"CHHW$566r<   )r<  r   rL   r  r3   r
   rP   rQ   rQ  binaryrZ  r  openForReadingr  r  )
rp   rI   rr  r  r  r   rx  r  r|  r  s
   `     @@@@r=   ftp_RETRFTP.ftp_RETRB  s     #%&VWW	7 !6!6=G 		
 {{'(8(89D##D	'	.		 			7 JJ%%g.	x*			-  o  	7::/566	7s   C )C?>C?c                   ^ ^^^^	 T R                   c  [        S5      e [        T R                  U5      m	T R                  S5        U 4S jnUUU4S jnU	4S jnU 4S jmS mS mT R                  R                  T	5      nUR                  X45        UR                  U5        U$ ! [         a"    [
        R                  " [        U5      5      s $ f = f)	a  
STORE (STOR)

This command causes the server-DTP to accept the data
transferred via the data connection and to store the data as
a file at the server site.  If the file specified in the
pathname exists at the server site, then its contents shall
be replaced by the data being transferred.  A new file is
created at the server site if the file specified in the
pathname does not already exist.
Nz.PORT, PASV, EPRT, or EPSV required before STORc                 R   > TR                  TR                  R                  5        U $ rl   rq  r  s    r=   rr  #FTP.ftp_STOR.<locals>.enableTimeout  rt  r<   c                    >^  T R                  5       nUR                  T5        UR                  U 4S j5        UR                  TT5        U$ )zT
File was open for reading. Launch the data transfer channel via
the file consumer.
c                 $   > TR                  5       $ rl   )rl  )r  r  s    r=   r  0FTP.ftp_STOR.<locals>.cbOpened.<locals>.<lambda>  s    $**,r<   )receiver  r  )r  r   
cbConsumerrx  r|  s   ` r=   r  FTP.ftp_STOR.<locals>.cbOpened  s<    
 AMM*%MM67NN66*Hr<   c                    > [        U R                  [        5      (       a'  U R                  R                  SR	                  T5      4$ [
        R                  " U S5        [        SR	                  T5      4$ )z
Called when failed to open the file for reading.

For known errors, return the FTP error code.
For all other, return a file not found error.
r?   z-Unexpected error received while opening file:)r  r  rj   ru   r  r   r  rz   r  s    r=   r  FTP.ftp_STOR.<locals>.ebOpened  sW     #))[11		++SXXg->??GGCHI"CHHW$566r<   c                   > TR                   (       d  [        U 5      n TR                  R                  U 5      nTR                  R                  (       a  TR                  [        5        U$ TR                  [        5        U$ )z
Called after the file was opended for reading.

Prepare the data transfer channel and send the response
to the command channel.
)r  rZ  r<  r!  r   r  rL  r  )r  r   rp   s     r=   r   FTP.ftp_STOR.<locals>.cbConsumer  se     ;;+D1  11$7A ++

:; H 

78Hr<   c                     [         4$ )z3
Called from data transport when transfer is done.
rv  rw  s    r=   rx  FTP.ftp_STOR.<locals>.cbSent  s     %&&r<   c                 v    [         R                  " U S5        U R                  [        5      (       a  U $ [        4$ )zG
Called from data transport when there are errors during the
transfer.
z*Unexpected error received during transfer:)r   r  r  rj   r{  r3  s    r=   r|  FTP.ftp_STOR.<locals>.ebSent  s0    
 GGCEFyy%%
+--r<   )r<  r   rL   r  r3   r
   rP   rQ   rQ  r  openForWritingr  r  )
rp   rI   rr  r  r  r   r  rx  r|  r  s
   `     @@@@r=   ftp_STORFTP.ftp_STOR  s     #%&VWW	7 !6!6=G 				
	7	(	'	. JJ%%g.	x*			-  [  	7::/566	7s   B% %)CCc                      [        U R                  U5      nS nU R                  R                  US5      R                  U5      $ ! [         a"    [        R                  " [        U5      5      s $ f = f)a  
File SIZE

The FTP command, SIZE OF FILE (SIZE), is used to obtain the transfer
size of a file from the server-FTP process.  This is the exact number
of octets (8 bit bytes) that would be transmitted over the data
connection should that file be transmitted.  This value will change
depending on the current STRUcture, MODE, and TYPE of the data
connection or of a data connection that would be created were one
created now.  Thus, the result of the SIZE command is dependent on
the currently established STRU, MODE, and TYPE parameters.

The SIZE command returns how many octets would be transferred if the
file were to be transferred using the current transfer structure,
mode, and type.  This command is normally used in conjunction with
the RESTART (REST) command when STORing a file to a remote server in
STREAM mode, to determine the restart point.  The server-PI might
need to read the partially transferred file, do any appropriate
conversion, and count the number of octets that would be generated
when sending the file in order to correctly respond to this command.
Estimates of the file transfer size MUST NOT be returned; only
precise information is acceptable.

http://tools.ietf.org/html/rfc3659
c                 ,    U u  n[         [        U5      4$ rl   )FILE_STATUSr   )r  r   s     r=   cbStatFTP.ftp_SIZE.<locals>.cbStat  s    GTT++r<   )r   	rL   r  r3   r
   rP   rQ   r  statr  rp   rI   r  r  s       r=   ftp_SIZEFTP.ftp_SIZE  sf    4	7 !6!6=G	, zzw	2>>vFF  	7::/566	7   A )A21A2c                      [        U R                  U5      nS nU R                  R                  US5      R                  U5      $ ! [         a"    [        R                  " [        U5      5      s $ f = f)a  
File Modification Time (MDTM)

The FTP command, MODIFICATION TIME (MDTM), can be used to determine
when a file in the server NVFS was last modified.  This command has
existed in many FTP servers for many years, as an adjunct to the REST
command for STREAM mode, thus is widely available.  However, where
supported, the "modify" fact that can be provided in the result from
the new MLST command is recommended as a superior alternative.

http://tools.ietf.org/html/rfc3659
c                 l    U u  n[         [        R                  " S[        R                  " U5      5      4$ )Nz%Y%m%d%H%M%S)r  r   strftimer   )r  r   s     r=   r  FTP.ftp_MDTM.<locals>.cbStat#  s(     KX~t{{8?T!UVVr<   )r   r  r  s       r=   ftp_MDTMFTP.ftp_MDTM  sg    	7 !6!6=G	W zzw6BB6JJ  	7::/566	7r  c                     UR                  5       nU(       a2  [        U SUS   -   S5      nUb  U" USS 5      $ U R                  U5      $ [        4$ )a  
REPRESENTATION TYPE (TYPE)

The argument specifies the representation type as described
in the Section on Data Representation and Storage.  Several
types take a second parameter.  The first parameter is
denoted by a single Telnet character, as is the second
Format parameter for ASCII and EBCDIC; the second parameter
for local byte is a decimal integer to indicate Bytesize.
The parameters are separated by a <SP> (Space, ASCII code
32).
type_r   Nr0   )r  r  type_UNKNOWNr   )rp   typer?  fs       r=   ftp_TYPEFTP.ftp_TYPE)  sU     JJLg!nd3A}12x$$Q''}r<   c                 |    US:X  d  US:X  a  SU l         [        SU-   4$ [        R                  " [	        U5      5      $ )NrA   NFAr  TYPE_SET_OKr
   rP   r   rp   codes     r=   type_A
FTP.type_A>  s:    2:DKt,,::/566r<   c                 j    US:X  a  SU l         [        S4$ [        R                  " [	        U5      5      $ )NrA   TIr  r  s     r=   type_I
FTP.type_IE  s0    2:DK%%::/566r<   c                 @    [         R                  " [        U5      5      $ rl   )r
   rP   r   r  s     r=   r  FTP.type_UNKNOWNL  s    zz6t<==r<   c                     [         $ rl   )NAME_SYS_TYPErv   s    r=   ftp_SYSTFTP.ftp_SYSTO  s    r<   c                 z    UR                  5       nUS:X  a  [        4$ [        R                  " [	        U5      5      $ )NFr  CMD_OKr
   rP   r   )rp   	structurer?  s      r=   ftp_STRUFTP.ftp_STRUR  s2    OO89zz6yABBr<   c                 z    UR                  5       nUS:X  a  [        4$ [        R                  " [	        U5      5      $ )NSr  )rp   moder?  s      r=   ftp_MODEFTP.ftp_MODEX  s1    JJL89zz6t<==r<   c                    ^  [        U R                  T5      nU R                  R                  U5      R                  U4S j5      $ ! [         a"    [        R                  " [        T5      5      s $ f = f)Nc                    > [         T4$ rl   )	MKD_REPLY)r  rI   s    r=   r  FTP.ftp_MKD.<locals>.<lambda>d  s
    D)r<   )	rL   r  r3   r
   rP   rQ   r  makeDirectoryr  rp   rI   r  s    ` r=   ftp_MKDFTP.ftp_MKD^  sg    	7 !6!6=G zz''0<<)
 	
  	7::/566	7s   A )A32A3c                      [        U R                  U5      nU R                  R                  U5      R                  S 5      $ ! [         a"    [        R                  " [        U5      5      s $ f = f)Nc                     [         4$ rl   rb  r   s    r=   r  FTP.ftp_RMD.<locals>.<lambda>m      35r<   )	rL   r  r3   r
   rP   rQ   r  removeDirectoryr  r  s      r=   ftp_RMDFTP.ftp_RMDg  sf    	7 !6!6=G zz))'2>>5
 	
  	7::/566	7   A )A/.A/c                      [        U R                  U5      nU R                  R                  U5      R                  S 5      $ ! [         a"    [        R                  " [        U5      5      s $ f = f)Nc                     [         4$ rl   r  r   s    r=   r  FTP.ftp_DELE.<locals>.<lambda>v  r  r<   )	rL   r  r3   r
   rP   rQ   r  
removeFiler  r  s      r=   ftp_DELEFTP.ftp_DELEp  sf    	7 !6!6=G zz$$W-995
 	
  	7::/566	7r  c                     [         4$ rl   )r  rv   s    r=   ftp_NOOPFTP.ftp_NOOPy  s
    yr<   c                 >    Xl         U R                  U l        [        4$ rl   )	_fromNamer  r  "REQ_FILE_ACTN_PENDING_FURTHER_INFO)rp   fromNames     r=   ftp_RNFRFTP.ftp_RNFR|  s    !]]
244r<   c                 N   U R                   nU ? U R                  U l         [        U R                  U5      n[        U R                  U5      nU R                  R                  X45      R                  S 5      $ ! [
         a"    [        R                  " [        U5      5      s $ f = f)Nc                     [         4$ rl   r  r   s    r=   r  FTP.ftp_RNTO.<locals>.<lambda>  r  r<   )r  r  r  rL   r  r3   r
   rP   rQ   r  renamer  )rp   toNamer  fromsegstosegss        r=   r  FTP.ftp_RNTO  s    >>N[[
	;!$"7"7BH 5 5v>F zz  2>>5
 	
  	;::/9::	;s   ,A8 8)B$#B$c                     U R                  [        [           S   5        U R                   H  nU R                  SU-   5        M     U R                  [        [           S   5        g)zU
Advertise the features supported by the server.

http://tools.ietf.org/html/rfc2389
r   r  r0   N)r   rt   FEAT_OKFEATURES)rp   features     r=   ftp_FEATFTP.ftp_FEAT  sN     	hw'*+}}GMM#-( %hw'*+r<   c                 .    U R                  [        U5      $ )zT
Handle OPTS command.

http://tools.ietf.org/html/draft-ietf-ftpext-utf-8-option-00
)r  OPTS_NOT_IMPLEMENTED)rp   options     r=   ftp_OPTSFTP.ftp_OPTS  s     zz.77r<   c                 p    U R                  [        5        U R                  R                  5         SU l        g r   )r  GOODBYE_MSGr   r  r  rv   s    r=   ftp_QUITFTP.ftp_QUIT  s&    

;%%' r<   c                    [         R                  " SSS9  [         R                  " U R                  5        U R                  Ssol        [        R                  R                  U5      (       a  UR                  5         O@[        R                  R                  U5      (       a  UR                  5         O SU< 35       eU R                  R                  5         SU l	        U R                  b  SU l        gg)z 
Call when DTP connection exits
r  Tr   Nz>dtpPort should be an IListeningPort or IConnector, instead is )r   rq   r  r   IListeningPort
providedBystopListening
IConnector
disconnectr  rC  r<  )rp   r  s     r=   r  FTP.cleanupDTP  s     	D) $d$$//88!!#""--g66 #*-5
 	##%'#D (r<   )r  r  r  r  r  r  r<  r  r  r  r  r   r  )rA   )Ir6   r7   r8   r9   r:   r  ranger  r  r  r  r  r	   r  r  r  r<  r  r  	_AFNUM_IPr"  r  r  r  r  r   	listenTCPr  r   r  r   r   r   r  r  r  r  r  r  r  r  r$  r;  rD  rG  rT  r^  rf  ri  rm  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r	  r  r  r;   __classcell__)r  s   @r=   rv  rv    sr   !F L (-Qx$FFFH JFEJGKFH"+Z!8v&O;HQ{%%MI=
(,1\!?F
.5$B-F^0)FVL2(LT>+ZN`F"BHT^@#GJK0*77>C>


5

	,8!
$ $r<   rv  c                   t    \ rS rSrSr\r\rSr	Sr
SrS\R                   S3r\" SS	5      rSS jrS rS rSrg
)
FTPFactoryi  a  
A factory for producing ftp protocol instances

@ivar timeOut: the protocol interpreter's idle timeout time in seconds,
    default is 600 seconds.

@ivar passivePortRange: value forwarded to C{protocol.passivePortRange}.
@type passivePortRange: C{iterator}
T	anonymousiX  zTwisted z FTP Serverr   r0   Nc                 *    Xl         X l        / U l        g rl   )r	   r  	instances)rp   r	   r  s      r=   rn   FTPFactory.__init__  s    *r<   c                     [         R                  R                  X5      nUbQ  U R                  UR                  l        U R
                  UR                  l        U R                  UR                  l        U$ rl   )r   LimitTotalConnectionsFactoryr@  r	   wrappedProtocolr  r  r=  s      r=   r@  FTPFactory.buildProtocol  sZ    11??K='+{{A$(,A%151F1FA.r<   c                     U R                    Vs/ s H"  oR                  c  M  UR                  S 5      PM$       n[        R                  R                  U 5        g s  snf rl   )r  r  rQ  r   r!  rC  )rp   r?  s     r=   rC  FTPFactory.stopFactory  sD     &*^^M^yy	d	^M--99$? 	Ns
   AA)r  r	   r  )Nr  )r6   r7   r8   r9   r:   rv  r   rq  overflowProtocolr  r  r  r   versionr  r  r  rn   r@  rC  r;   r5   r<   r=   r  r    sT     H*NMG	 1 12+>NQ{
@r<   r  c                   V    \ rS rSrSrS rS rS rS rS r	SS	 jr
SS
 jrS rS rSrg)r  i  z{
An abstraction of the shell commands used by the FTP protocol for
a given user account.

All path names must be absolute.
c                     g)z
Create a directory.

@param path: The path, as a list of segments, to create
@type path: C{list} of C{unicode}

@return: A Deferred which fires when the directory has been
created, or which fails if the directory cannot be created.
Nr5   rI   s    r=   r  IFTPShell.makeDirectory      r<   c                     g)z
Remove a directory.

@param path: The path, as a list of segments, to remove
@type path: C{list} of C{unicode}

@return: A Deferred which fires when the directory has been
removed, or which fails if the directory cannot be removed.
Nr5   r*  s    r=   r  IFTPShell.removeDirectory  r,  r<   c                     g)z
Remove a file.

@param path: The path, as a list of segments, to remove
@type path: C{list} of C{unicode}

@return: A Deferred which fires when the file has been
removed, or which fails if the file cannot be removed.
Nr5   r*  s    r=   r  IFTPShell.removeFile
  r,  r<   c                     g)a8  
Rename a file or directory.

@param fromPath: The current name of the path.
@type fromPath: C{list} of C{unicode}

@param toPath: The desired new name of the path.
@type toPath: C{list} of C{unicode}

@return: A Deferred which fires when the path has been
renamed, or which fails if the path cannot be renamed.
Nr5   )fromPathtoPaths     r=   r  IFTPShell.rename  r,  r<   c                     g)z
Determine whether access to the given path is allowed.

@param path: The path, as a list of segments

@return: A Deferred which fires with None if access is allowed
or which fails with a specific exception type if access is
denied.
Nr5   r*  s    r=   re  IFTPShell.access#  r,  r<   r5   c                     g)zw
Retrieve information about the given path.

This is like list, except it will never return results about
child paths.
Nr5   rI   keyss     r=   r  IFTPShell.stat.  r,  r<   c                     g)a  
Retrieve information about the given path.

If the path represents a non-directory, the result list should
have only one entry with information about that non-directory.
Otherwise, the result list should have an element for each
child of the directory.

@param path: The path, as a list of segments, to list
@type path: C{list} of C{unicode} or C{bytes}

@param keys: A tuple of keys desired in the resulting
dictionaries.

@return: A Deferred which fires with a list of (name, list),
where the name is the name of the entry as a unicode string or
bytes and each list contains values corresponding to the requested
keys.  The following are possible elements of keys, and the
values which should be returned for them:

    - C{'size'}: size in bytes, as an integer (this is kinda required)

    - C{'directory'}: boolean indicating the type of this entry

    - C{'permissions'}: a bitvector (see os.stat(foo).st_mode)

    - C{'hardlinks'}: Number of hard links to this entry

    - C{'modified'}: number of seconds since the epoch since entry was
      modified

    - C{'owner'}: string indicating the user owner of this entry

    - C{'group'}: string indicating the group owner of this entry
Nr5   r8  s     r=   rS  IFTPShell.list6  r,  r<   c                     g)z
@param path: The path, as a list of segments, to open
@type path: C{list} of C{unicode}

@rtype: C{Deferred} which will fire with L{IReadFile}
Nr5   r*  s    r=   r  IFTPShell.openForReading[  r,  r<   c                     g)z
@param path: The path, as a list of segments, to open
@type path: C{list} of C{unicode}

@rtype: C{Deferred} which will fire with L{IWriteFile}
Nr5   r*  s    r=   r  IFTPShell.openForWritingc  r,  r<   Nr5   )r6   r7   r8   r9   r:   r  r  r  r  re  r  rS  r  r  r;   r5   r<   r=   r  r    s5    				#Jr<   r  c                       \ rS rSrSrS rSrg)	IReadFileil  z(
A file out of which bytes may be read.
c                     g)z
Produce the contents of the given path to the given consumer.  This
method may only be invoked once on each provider.

@type consumer: C{IConsumer}

@return: A Deferred which fires when the file has been
consumed completely.
Nr5   )consumers    r=   r  IReadFile.sendq  r,  r<   r5   N)r6   r7   r8   r9   r:   r  r;   r5   r<   r=   rC  rC  l  s    	r<   rC  c                   $    \ rS rSrSrS rS rSrg)
IWriteFilei}  z)
A file into which bytes may be written.
c                      g)z
Create a consumer which will write to this file.  This method may
only be invoked once on each provider.

@rtype: C{Deferred} of C{IConsumer}
Nr5   r5   r<   r=   r  IWriteFile.receive  r,  r<   c                      g)a-  
Perform any post-write work that needs to be done. This method may
only be invoked once on each provider, and will always be invoked
after receive().

@rtype: C{Deferred} of anything: the value is ignored. The FTP client
will not see their upload request complete until this Deferred has
been fired.
Nr5   r5   r<   r=   rl  IWriteFile.close  r,  r<   r5   N)r6   r7   r8   r9   r:   r  rl  r;   r5   r<   r=   rH  rH  }  s    	r<   rH  c                    / n[         R                  " U 5      nUR                  UR                  5        [        R
                  " 5        H:  nUR                  UR                  ;   d  M  UR                  UR                  5        M<     U$ )zS
Return the primary and supplementary groups for the given UID.

@type uid: C{int}
)	pwdgetpwuidrG   pw_gidgrpgetgrallpw_namegr_memgr_gid)uidr  pwentgrents       r=   
_getgroupsrY    s^     FLLE
MM%,,==ELL(MM%,,'   Mr<   c                 .   US:X  aA  [         R                  n[         R                  n[         R                  n[        R
                  nOWUS:X  aA  [         R                  n[         R                  n[         R                  n[        R                  nO[        SU< S35      eSn[        R                  R                  U5      (       a~  U S:X  a  SnOu[        R                   " U5      n	XIR                  -  (       a  X	R                  :X  a  SnO:XYR                  -  (       a  U[        U 5      ;   a  SnOXiR                  -  (       a  SnU(       aK  [        R                   " X'5      (       d0  Sn["        R$                  " SU [        R&                  " 5       4-  5        U$ )	a  
checks to see if uid has proper permissions to access path with mode

@type uid: C{int}
@param uid: numeric user id

@type gid: C{int}
@param gid: numeric group id

@type spath: C{str}
@param spath: the path on the server to test

@type mode: C{str}
@param mode: 'r' or 'w' (read or write)

@rtype: C{bool}
@return: True if the given credentials have the specified form of
    access to the given path
rwzInvalid mode z: must specify 'r' or 'w'Fr   TzUFilesystem grants permission to UID %d but it is inaccessible to me running as UID %d)r  S_IRUSRS_IRGRPS_IROTHr]  R_OKS_IWUSRS_IWGRPS_IWOTHW_OKr  rI   existsst_modest_uidrY  re  r   rq   getuid)
rV  gidspathr  usrrQ  othamodere  rK   s
             r=   _testPermissionsrn    s    ( s{llllll	llllll=0IJKKF	ww~~e!8FAYY3((?yySJsO%;yyyy&&FGG7:=ryy{9KL Mr<   c                       \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rSS jrSS jrS rS rS rS rS rS rS rS rSrg)FTPAnonymousShelli  z
An anonymous implementation of IFTPShell

@type filesystemRoot: L{twisted.python.filepath.FilePath}
@ivar filesystemRoot: The path which is considered the root of
this shell.
c                     Xl         g rl   filesystemRoot)rp   rs  s     r=   rn   FTPAnonymousShell.__init__  s    ,r<   c                 8    U R                   R                  U5      $ rl   )rs  
descendantrp   rI   s     r=   _pathFTPAnonymousShell._path  s    ""--d33r<   c                 >    [         R                  " [        5       5      $ rl   r
   rP   r|   rw  s     r=   r  FTPAnonymousShell.makeDirectory      zz-/00r<   c                 >    [         R                  " [        5       5      $ rl   r{  rw  s     r=   r  !FTPAnonymousShell.removeDirectory  r}  r<   c                 >    [         R                  " [        5       5      $ rl   r{  rw  s     r=   r  FTPAnonymousShell.removeFile  r}  r<   c                 >    [         R                  " [        5       5      $ rl   r{  )rp   r2  r3  s      r=   r  FTPAnonymousShell.rename  r}  r<   c                 `    U R                  U5      n[        R                  " [        5       5      $ rl   )rx  r
   rP   r|   rw  s     r=   r  FTPAnonymousShell.receive  s#    zz$zz-/00r<   c                    U R                  U5      nUR                  5       (       a  [        R                  " [	        U5      5      $  UR                  S5      n[        R                  " [        U5      5      $ ! [         a   n[        UR                  U5      s SnA$ SnAf[         a    [        R                  " 5       s $ f = f)a  
Open C{path} for reading.

@param path: The path, as a list of segments, to open.
@type path: C{list} of C{unicode}
@return: A L{Deferred} is returned that will fire with an object
    implementing L{IReadFile} if the file is successfully opened.  If
    C{path} is a directory, or if an exception is raised while trying
    to open the file, the L{Deferred} will fire with an error.
r[  N)rx  isdirr
   rP   rZ   openr  _FileReaderOSErrorr\   rN   r  )rp   rI   r?  r  r[   s        r=   r   FTPAnonymousShell.openForReading   s     JJt7799 ::/566	1sA ==Q00  	1!!''400 	 ::<	 $   A7 7
CBC"C Cc                 @    [         R                  " [        S5      5      $ )zI
Reject write attempts by anonymous users with
L{PermissionDeniedError}.
zSTOR not allowed)r
   rP   rT   rw  s     r=   r   FTPAnonymousShell.openForWriting  s    
 zz/0BCDDr<   c                 t   U R                  U5      nUR                  5       (       d  [        R                  " [	        U5      5      $  UR                  5         [        R                  " S 5      $ ! [         a   n[        UR                  U5      s S nA$ S nAf[         a    [        R                  " 5       s $ f = frl   )rx  re  r
   rP   rQ   listdirr  r  r\   rN   r  rp   rI   r?  r[   s       r=   re  FTPAnonymousShell.access   s    JJtxxzz ::/566	'IIK ==&&  	1!!''400 	 ::<	 $   A- -
B77BB7"B76B7c                 z   U R                  U5      nUR                  5       (       a(   U R                  X25      n[        R                  " U5      $ U R                  X5      R                  S 5      $ ! [
         a   n[        UR                  U5      s S nA$ S nAf[         a    [        R                  " 5       s $ f = f)Nc                     U S   S   $ )Nr   r0   r5   )ress    r=   r  (FTPAnonymousShell.stat.<locals>.<lambda><  s    Qr<   )rx  r  	_statNoder
   r  r  r\   rN   r  rP   rS  r  )rp   rI   r9  r?  
statResultr[   s         r=   r  FTPAnonymousShell.stat0  s    JJt77991!^^A4
 }}Z0099T(445JKK  5%aggt44  $zz|#$s#   A0 0
B::BB:"B:9B:c                    U R                  U5      nUR                  5       (       a1  UR                  5       nU Vs/ s H  oSR                  U5      PM     nnOoUR	                  5       (       a;  [
        R                  R                  " UR                  U R                  5      6 /nU/nO[        R                  " [        U5      5      $ / n[        XF5       HC  u  p/ n	UR                  X45        U(       d  M"   U	R                  U R!                  X25      5        ME     [        R*                  " U5      $ s  snf ! ["         a"  n
[%        U
R&                  U5      s Sn
A
s  $ Sn
A
f[(         a    [        R                  " 5       s s  $ f = f)z
Return the list of files at given C{path}, adding C{keys} stat
informations if specified.

@param path: the directory or file to check.
@type path: C{str}

@param keys: the list of desired metadata
@type keys: C{list} of C{str}
N)rx  r  r  childisfiler]  rI   r  segmentsFromrs  r
   rP   rQ   ziprG   extendr  r  r\   rN   r  r  )rp   rI   r9  filePathentriesr?  fileEntriesrN  fileNameentr[   s              r=   rS  FTPAnonymousShell.list>  s/    ::d#>>&&(G6=>g>>!,gK>K__ww||X%:%:4;N;N%OPQG#*K::/566"%g";HCNNH?+t(JJt~~h=> #< }}W%%' ?  =)!''8<<$ ( ::<'(s)   D17 D66
F EF"FFc                 x    UR                  5         U Vs/ s H  n[        U SU-   5      " U5      PM     sn$ s  snf )z
Shortcut method to get stat info on a node.

@param filePath: the node to stat.
@type filePath: C{filepath.FilePath}

@param keys: the stat keys to get.
@type keys: C{iterable}
_stat_)restatr  )rp   r  r9  ks       r=   r  FTPAnonymousShell._statNodea  s6     	?CDt!hl+H5tDDDs   7c                 "    UR                  5       $ )zy
Get the filepath's size as an int

@param fp: L{twisted.python.filepath.FilePath}
@return: C{int} representing the size
)getsizerp   fps     r=   
_stat_sizeFTPAnonymousShell._stat_sizen  s     zz|r<   c                 "    UR                  5       $ )z
Get the filepath's permissions object

@param fp: L{twisted.python.filepath.FilePath}
@return: L{twisted.python.filepath.Permissions} of C{fp}
)getPermissionsr  s     r=   _stat_permissions#FTPAnonymousShell._stat_permissionsw  s       ""r<   c                 D     UR                  5       $ ! [         a     gf = f)av  
Get the number of hardlinks for the filepath - if the number of
hardlinks is not yet implemented (say in Windows), just return 0 since
stat-ing a file in Windows seems to return C{st_nlink=0}.

(Reference:
U{http://stackoverflow.com/questions/5275731/os-stat-on-windows})

@param fp: L{twisted.python.filepath.FilePath}
@return: C{int} representing the number of hardlinks
r   )getNumberOfHardLinksNotImplementedErrorr  s     r=   _stat_hardlinks!FTPAnonymousShell._stat_hardlinks  s(    	**,," 		s    
c                 "    UR                  5       $ )z
Get the filepath's last modified date

@param fp: L{twisted.python.filepath.FilePath}
@return: C{int} as seconds since the epoch
)getModificationTimer  s     r=   _stat_modified FTPAnonymousShell._stat_modified  s     %%''r<   c                      UR                  5       n[        b   [        R                  " U5      S   $ [	        U5      $ ! [         a     Nf = f! [
         a     gf = f)aX  
Get the filepath's owner's username.  If this is not implemented
(say in Windows) return the string "0" since stat-ing a file in
Windows seems to return C{st_uid=0}.

(Reference:
U{http://stackoverflow.com/questions/5275731/os-stat-on-windows})

@param fp: L{twisted.python.filepath.FilePath}
@return: C{str} representing the owner's username
r   0)	getUserIDrN  rO  KeyErrorr   r  )rp   r  userIDs      r=   _stat_ownerFTPAnonymousShell._stat_owner  se    
	\\^F <</22 v;    # 		    A > 
A
A
AAc                      UR                  5       n[        b   [        R                  " U5      S   $ [	        U5      $ ! [         a     Nf = f! [
         a     gf = f)aR  
Get the filepath's owner's group.  If this is not implemented
(say in Windows) return the string "0" since stat-ing a file in
Windows seems to return C{st_gid=0}.

(Reference:
U{http://stackoverflow.com/questions/5275731/os-stat-on-windows})

@param fp: L{twisted.python.filepath.FilePath}
@return: C{str} representing the owner's group
r   r  )
getGroupIDrQ  getgrgidr  r   r  )rp   r  groupIDs      r=   _stat_groupFTPAnonymousShell._stat_group  se    
	 mmoG <<033 w<    # 		r  c                 "    UR                  5       $ )zj
Get whether the filepath is a directory

@param fp: L{twisted.python.filepath.FilePath}
@return: C{bool}
)r  r  s     r=   _stat_directory!FTPAnonymousShell._stat_directory  s     xxzr<   rr  NrA  )r6   r7   r8   r9   r:   rn   rx  r  r  r  r  r  r  r  re  r  rS  r  r  r  r  r  r  r  r  r;   r5   r<   r=   rp  rp    so    -41111112E' L!&FE#"(0 0r<   rp  c                   &    \ rS rSrS rS rS rSrg)r  i  c                     Xl         SU l        g r   )rf  _sendrg  s     r=   rn   _FileReader.__init__  s    	
r<   c                 H    SU l         U R                  R                  5         U$ r   )r  rf  rl  )rp   passthroughs     r=   _close_FileReader._close  s    
		r<   c                     U R                   (       a   S5       eSU l         [        R                  " 5       R                  U R                  U5      nUR                  U R                  5        U$ )Nz0Can only call IReadFile.send *once* per instanceT)r  r   
FileSenderbeginFileTransferrf  r  r  )rp   rE  r   s      r=   r  _FileReader.send  sO    ::QQQ~
00HE			$++r<   )r  rf  N)r6   r7   r8   r9   rn   r  r  r;   r5   r<   r=   r  r    s    
r<   r  c                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
FTPShelli  z2
An authenticated implementation of L{IFTPShell}.
c                    U R                  U5      n UR                  5         [        R                  " S 5      $ ! [         a   n[        UR                  U5      s S nA$ S nAf[         a    [        R                  " 5       s $ f = frl   )	rx  makedirsr
   r  r  r\   rN   r  rP   r  s       r=   r  FTPShell.makeDirectory  sf    JJt	'JJL ==&&  	1!!''400 	 ::<	 s!   9 
BAB"BBc                    U R                  U5      nUR                  5       (       a  [        R                  " [	        U5      5      $  [
        R                  " UR                  5        [        R                  " S 5      $ ! [         a   n[        UR                  U5      s S nA$ S nAf[         a    [        R                  " 5       s $ f = frl   )rx  r  r
   rP   rV   r]  rmdirrI   r  r  r\   rN   r  r  s       r=   r  FTPShell.removeDirectory  s    JJt88:: ::24899	'HHQVV ==&&  	1!!''400 	 ::<	 s$    A= =
CB"C""CCc                 t   U R                  U5      nUR                  5       (       a  [        R                  " [	        U5      5      $  UR                  5         [        R                  " S 5      $ ! [         a   n[        UR                  U5      s S nA$ S nAf[         a    [        R                  " 5       s $ f = frl   )rx  r  r
   rP   rZ   remover  r  r\   rN   r  r  s       r=   r  FTPShell.removeFile	  s    JJt7799 ::/566	'HHJ ==&&  	1!!''400 	 ::<	 r  c                 d   U R                  U5      nU R                  U5      n [        R                  " UR                  UR                  5        [        R
                  " S 5      $ ! [         a   n[        UR                  U5      s S nA$ S nAf[         a    [        R                  " 5       s $ f = frl   )rx  r]  r  rI   r
   r  r  r\   rN   r  rP   )rp   r2  r3  r  tpr[   s         r=   r  FTPShell.rename	  s    ZZ!ZZ	'IIbggrww' ==&&  	5!!''844 	 ::<	 s#   +A% %
B//B
B/
"B/.B/c                    U R                  U5      nUR                  5       (       a  [        R                  " [	        U5      5      $  UR                  S5      n[        R                  " [        U5      5      $ ! [         a   n[        UR                  U5      s SnA$ SnAf[         a    [        R                  " 5       s $ f = f)a  
Open C{path} for writing.

@param path: The path, as a list of segments, to open.
@type path: C{list} of C{unicode}
@return: A L{Deferred} is returned that will fire with an object
    implementing L{IWriteFile} if the file is successfully opened.  If
    C{path} is a directory, or if an exception is raised while trying
    to open the file, the L{Deferred} will fire with an error.
r\  N)rx  r  r
   rP   rZ   r  r  r\   rN   r  r  _FileWriter)rp   rI   r?  rf  r[   s        r=   r  FTPShell.openForWriting#	  s     JJt7799 ::/566	 66#;D
 }}[.//	  	1!!''400 	 ::<	 r  r5   N)r6   r7   r8   r9   r:   r  r  r  r  r  r;   r5   r<   r=   r  r    s     	'' ' 
'0r<   r  c                   &    \ rS rSrS rS rS rSrg)r  i<	  c                     Xl         SU l        g r   )rf  _receiverg  s     r=   rn   _FileWriter.__init__>	  s    	r<   c                     U R                   (       a   S5       eSU l         [        R                  " [        U R                  5      5      $ )Nz4Can only call IWriteFile.receive *once* per instanceT)r  r
   r  rd  rf  rv   s    r=   r  _FileWriter.receiveB	  s4    ==X"XX }}\$))455r<   c                 .    [         R                  " S 5      $ rl   )r
   r  rv   s    r=   rl  _FileWriter.closeH	  s    }}T""r<   )r  rf  N)r6   r7   r8   r9   rn   r  rl  r;   r5   r<   r=   r  r  <	  s    6#r<   r  c                   *    \ rS rSrSrS rS rS rSrg)BaseFTPRealmiL	  zo
Base class for simple FTP realms which provides an easy hook for specifying
the home directory for each user.
c                 :    [         R                  " U5      U l        g rl   )r   FilePathanonymousRoot)rp   r  s     r=   rn   BaseFTPRealm.__init__S	  s    %..}=r<   c                 4    [        U R                  < S35      e)z
Return a L{FilePath} representing the home directory of the given
avatar.  Override this in a subclass.

@param avatarId: A user identifier returned from a credentials checker.
@type avatarId: C{str}

@rtype: L{FilePath}
z" did not override getHomeDirectory)r  r  rp   avatarIds     r=   getHomeDirectoryBaseFTPRealm.getHomeDirectoryV	  s!     "~~  BC
 	
r<   c                     U Hf  nU[         L d  M  U[        R                  L a  [        U R                  5      nO[        U R                  U5      5      n[         U[        USS 5      4s  $    [        S5      e)Nr  c                      g rl   r5   r5   r<   r=   r  ,BaseFTPRealm.requestAvatar.<locals>.<lambda>k	  s    Tr<   z3Only IFTPShell interface is supported by this realm)	r  r   	ANONYMOUSrp  r  r  r  r  r  )rp   r  mindr   ifacer  s         r=   requestAvatarBaseFTPRealm.requestAvatard	  sk    E	!x111.t/A/ABF%d&;&;H&EFF!6768\+RSS   ""WXXr<   )r  N)	r6   r7   r8   r9   r:   rn   r  r  r;   r5   r<   r=   r  r  L	  s    
>
Yr<   r  c                   (    \ rS rSrSrSS jrS rSrg)FTPRealmio	  a
  
@type anonymousRoot: L{twisted.python.filepath.FilePath}
@ivar anonymousRoot: Root of the filesystem to which anonymous
    users will be granted access.

@type userHome: L{filepath.FilePath}
@ivar userHome: Root of the filesystem containing user home directories.
c                 d    [         R                  X5        [        R                  " U5      U l        g rl   )r  rn   r   r  userHome)rp   r  r  s      r=   rn   FTPRealm.__init__y	  s"    d2 ))(3r<   c                 8    U R                   R                  U5      $ )zj
Use C{avatarId} as a single path segment to construct a child of
C{self.userHome} and return that child.
)r  r  r  s     r=   r  FTPRealm.getHomeDirectory}	  s    
 }}""8,,r<   )r  N)z/home)r6   r7   r8   r9   r:   rn   r  r;   r5   r<   r=   r	  r	  o	  s    4-r<   r	  c                       \ rS rSrSrS rSrg)SystemFTPRealmi	  z
L{SystemFTPRealm} uses system user account information to decide what the
home directory for a particular avatarId is.

This works on POSIX but probably is not reliable on Windows.
c                     [         R                  R                  SU-   5      nUR                  S5      (       a  [        R
                  " 5       e[        R                  " U5      $ )z`
Return the system-defined home directory of the system user account
with the name C{avatarId}.
~)r]  rI   
expanduserrD   r  r  r   r  )rp   r  rI   s      r=   r  SystemFTPRealm.getHomeDirectory	  sK    
 ww!!#.1??3..00  &&r<   r5   N)r6   r7   r8   r9   r:   r  r;   r5   r<   r=   r  r  	  s    'r<   r  c                       \ rS rSrSrg)ConnectionLosti	  r5   Nr   r5   r<   r=   r  r  	  r   r<   r  c                       \ rS rSrSrg)CommandFailedi	  r5   Nr   r5   r<   r=   r  r  	  r   r<   r  c                       \ rS rSrSrg)BadResponsei	  r5   Nr   r5   r<   r=   r  r  	  r   r<   r  c                       \ rS rSrSrg)UnexpectedResponsei	  r5   Nr   r5   r<   r=   r  r  	  r   r<   r  c                       \ rS rSrSrg)UnexpectedDatai	  r5   Nr   r5   r<   r=   r  r  	  r   r<   r  c                   $    \ rS rSrSS jrS rSrg)
FTPCommandi	  Nc                 l    Xl         [        R                  " 5       U l        SU l        X l        S U l        g )Nr0   )textr
   r  r   readypublictransferDeferred)rp   r"  r$  s      r=   rn   FTPCommand.__init__	  s)    	(
 $r<   c                 ^    U R                   (       a  U R                  R                  U5        g g rl   )r$  r   r  )rp   r   s     r=   rP   FTPCommand.fail	  s     ;;MM!!'* r<   )r   r$  r#  r"  r%  Nr   )r6   r7   r8   r9   rn   rP   r;   r5   r<   r=   r   r   	  s    %+r<   r   c                   ,    \ rS rSrS rS rS rS rSrg)ProtocolWrapperi	  c                     Xl         X l        g rl   )originalr   )rp   r-  r   s      r=   rn   ProtocolWrapper.__init__	  s      r<   c                 :    U R                   R                  U5        g rl   )r-  makeConnectionrp   r   s     r=   r0  ProtocolWrapper.makeConnection	  s    $$Y/r<   c                 :    U R                   R                  U5        g rl   )r-  r  r  s     r=   r  ProtocolWrapper.dataReceived	  s    ""4(r<   c                 p    U R                   R                  U5        U R                  R                  S 5        g rl   )r-  r   r   r   r   s     r=   r   ProtocolWrapper.connectionLost	  s&    $$V,t$r<   )r   r-  N)	r6   r7   r8   r9   rn   r0  r  r   r;   r5   r<   r=   r+  r+  	  s    !0)%r<   r+  c                       \ rS rSrSrS rSrg)IFinishableConsumeri	  z5
A Consumer for producers that finish.

@since: 11.0
c                      g)z&
The producer has finished producing.
Nr5   r5   r<   r=   finishIFinishableConsumer.finish	  r,  r<   r5   N)r6   r7   r8   r9   r:   r:  r;   r5   r<   r=   r8  r8  	  s    r<   r8  c                   D    \ rS rSrS rS rS rS rS rS r	S r
S	 rS
rg)SenderProtocoli	  c                 l    [         R                  " 5       U l        [         R                  " 5       U l        g rl   )r
   r  connectedDeferredr   rv   s    r=   rn   SenderProtocol.__init__	  s!    !&!1 (r<   c                     [        S5      e)Nz<Received data from the server on a send-only data-connection)r  r  s     r=   r  SenderProtocol.dataReceived	  s    M
 	
r<   c                 x    [         R                  R                  X5        U R                  R	                  U 5        g rl   )r   Protocolr0  r?  r   r1  s     r=   r0  SenderProtocol.makeConnection	  s*    ((9''-r<   c                     UR                  [        R                  5      (       a  U R                  R	                  S5        g U R                  R                  U5        g )Nzconnection done)r  r   ConnectionDoner   r   r  r   s     r=   r   SenderProtocol.connectionLost	  s<    <<,,--MM""#45MM!!&)r<   c                 :    U R                   R                  U5        g rl   r   r  s     r=   r   SenderProtocol.write
  s    T"r<   c                 :    U R                   R                  X5        g)z1
Register the given producer with our transport.
Nr   r   s      r=   r   SenderProtocol.registerProducer
  s     	''<r<   c                 8    U R                   R                  5         g)z0
Unregister the previously registered producer.
N)r   r  rv   s    r=   r  !SenderProtocol.unregisterProducer
  s     	))+r<   c                 8    U R                   R                  5         g rl   r  rv   s    r=   r:  SenderProtocol.finish
  r)  r<   )r?  r   N)r6   r7   r8   r9   rn   r  r0  r   r   r   r  r:  r;   r5   r<   r=   r=  r=  	  s*    )

.*#=,(r<   r=  c                 N   [         R                  " SSU 5      nUR                  S5       Vs/ s H  n[        UR	                  5       5      PM     nnU H  nUS:  d  US:  d  M  [        SX5      e   Uu  pVpxpU SU SU SU 3n[        U	5      S-  [        U
5      -   nX4$ s  snf )	zY
Decode an FTP response specifying a host and port.

@return: a 2-tuple of (host, port).
z[^0-9, ]rA   r  r      zOut of ranger@   r   )resubrE   r  stripr  )r   abcdefr?  parsedxabcr   r[   r  r  r  s                r=   decodeHostPortr\  
  s     VVJD)F&,ll3&78&7c!'')n&7F8q5AG^T55  A!S!AaS!DFaK3q6!D: 9s   #B"c                     U R                  S5      [        US-	  5      [        US-  5      /-   nSR                  U5      $ )Nr@   r      r  )rE   r   r  )r  r  numberss      r=   r  r  '
  s8    jjoTQYTCZ AAG88Gr<   c                 T    U S   nU SS R                  U5      u  p#pEX#[        U5      4$ )z
Decode an FTP protocol/address/port combination, using the syntax
defined in RFC 2428 section 2.

@return: a 3-tuple of (protocol, host, port).
r   r0   N)rE   r  )r  delimr   r  r  r   s         r=   rB  rB  ,
  s7     AJE%abk//6HD3t9$$r<   c                 n    U R                   " [        R                  5        U R                  R                  $ rl   )r  r
   
FirstErrorr  
subFailure)r   s    r=   _unwrapFirstErrorre  8
  s$    LL!!"==###r<   c                   "    \ rS rSrSrSrS rSrg)FTPDataPortFactoryi=
  zS
Factory for data connections that use the PORT command

(i.e. "active" transfers)
Fc                 n    X R                   l        U R                  R                  5         U R                   $ rl   )r   r   r  r  )rp   r>  s     r=   r@   FTPDataPortFactory.buildProtocolF
  s(    
 !%		  "}}r<   r5   N)r6   r7   r8   r9   r:   noisyr@  r;   r5   r<   r=   rg  rg  =
  s     Er<   rg  c                   l    \ rS rSrSrSrSrS rS rS r	S r
S	 rS
 rS rSS jrS rS rS rS rSrg)FTPClientBasiciP
  z
Foundations of an FTP client.
Fr   c                     / U l         S U l        [        R                  " 5       R	                  U R
                  5      U l        U R                  R                  U R                  5        / U l	        SU l
        g r)  )actionQueuegreetingr
   r  r  _cb_greetingnextDeferredr  rP   rw   _failedrv   s    r=   rn   FTPClientBasic.__init__X
  sW    !NN,889J9JK$$TYY/r<   c                 &    U R                  U5        g)z(
Give an error to any queued deferreds.
N_failrp   r   s     r=   rP   FTPClientBasic.fail`
  s     	

5r<   c           	         U R                   (       a  U$ SU l         U R                  (       a:   U R                  R                  [        R                  " [        SU5      5      5        U R                   H2  nUR                  [        R                  " [        SU5      5      5        M4     U$ ! [        R                   a     NZf = f)z
Errback all queued deferreds.
r0   zFTP connection lost)
rr  rq  r  r   Failurer  r
   AlreadyCalledErrorrn  rP   )rp   r   
ftpCommands      r=   rv  FTPClientBasic._failf
  s     <<L!!))OON3H%$PQ
 **JOO/De LM +  ++ s   9B* *C Cc                     Xl         g rl   )ro  )rp   ro  s     r=   rp  FTPClientBasic._cb_greeting{
  s     r<   c                     Uc  g[        U[        5      (       a  UR                  U R                  5      n[        R
                  R                  X5        g)zb
Sends a line, unless line is None.

@param line: Line to send
@type line: L{bytes} or L{unicode}
N)r  r   r   r   r   LineReceiverr   r   s     r=   r   FTPClientBasic.sendLine~
  s?     <c"";;t~~.D##D/r<   c                    U R                  5       nUc  SU l        gUR                  (       dE  U R                  R	                  SU5        [
        R                  " SU R                  5        SU l        gUR                  S:X  a  U R                  U5        U R                  (       a#  [        R                  " SUR                  -  5        UR                  U l        U R                  UR                  5        g)z4
(Private) Processes the next command in the queue.
Nr   g      ?PORTz<-- %s)popCommandQueuerq  r#  rn  insertr   rO  sendNextCommandr"  generatePortCommandr   r   rq   r   r   rp   r|  s     r=   r  FTPClientBasic.sendNextCommand
  s     ))+
 $D##Az2c4#7#78 $D ??f$$$Z0::GGHz./&//joo&r<   c                     U R                   R                  U5        [        U R                   5      S:X  a-  U R                  b  U R                  c  U R                  5         gggg)z
Add an FTPCommand object to the queue.

If it's the only thing in the queue, and we are connected and we aren't
waiting for a response of an earlier command, the command will be sent
immediately.

@param ftpCommand: an L{FTPCommand}
r0   N)rn  rG   r_  r   rq  r  r  s     r=   queueCommandFTPClientBasic.queueCommand
  s\     	
+  !Q&*!!)  " * + 'r<   c                 R    [        X5      nU R                  U5        UR                  $ )a=  
Queues a string to be issued as an FTP command

@param command: string of an FTP command to queue
@param public: a flag intended for internal use by FTPClient.  Don't
    change it unless you know what you're doing.

@return: a L{Deferred} that will be called when the response to the
    command has been received.
)r   r  r   )rp   r  r$  r|  s       r=   queueStringCommand!FTPClientBasic.queueStringCommand
  s(      0
*%"""r<   c                 \    U R                   (       a  U R                   R                  S5      $ g)zB
Return the front element of the command queue, or None if empty.
r   N)rn  rF   rv   s    r=   r  FTPClientBasic.popCommandQueue
  s'     ##''**r<   c                 h  ^ ^ / nT R                  SU-   SS9nUR                  U5        UbQ  [        SU-   SS9mT R                  T5        UR                  TR                  5        UU 4S jnUR                  U5        U H0  nUR                  T R                  5        UR                  S 5        M2     g)z
Login: send the username, send the password.

If the password is L{None}, the PASS command won't be sent.  Also, if
the response to the USER command has a response code of 230 (User
logged in), then PASS won't be sent either.
zUSER r   r$  NzPASS c                 p   > U S   R                  S5      (       a  TR                  R                  T5        U $ )Nr   230)rD   rn  r  )rw   passwordCmdrp   s    r=   cancelPasswordIfNotNeeded<FTPClientBasic.queueLogin.<locals>.cancelPasswordIfNotNeeded
  s1    A;))%00$$++K8r<   c                     g rl   r5   rX  s    r=   r  +FTPClientBasic.queueLogin.<locals>.<lambda>
  s    $r<   )r  rG   r   r  r   r  r  rP   )rp   r  r  	deferredsuserDeferredr  r   r  s   `      @r=   
queueLoginFTPClientBasic.queueLogin
  s     	..w/A!.L& $Wx%7BKk*[112  $$%>? "H		*/	 "r<   c                 :   UR                  U R                  5      nU R                  (       a  [        R                  " SU-  5        U R
                  R                  U5        [        R                  " SU5      nU(       d  gUSS nUS   S:X  a  gU R                  c%  U R                  [        U R
                  5      5        gU R
                  n/ U l        US   S;   a  U R                  R                  U5        OUS   S;   a9  U R                  R                  [        R                  " [!        U5      5      5        OQ[        R                  " S	U 35        U R                  R                  [        R                  " [#        U5      5      5        U R%                  5         g)
z=
(Private) Parses the response messages from the FTP server.
z--> %sz\d{3} Nr      1)23)45z"Server sent invalid response code )r  r   r   r   rq   rw   rG   rS  matchrq  rP   r  r   r  r   rz  r  r  r  )rp   r   codeIsValidr  rw   s        r=   r  FTPClientBasic.lineReceived
  sA   
 {{4>>*::GGHtO$T" hhy$/Aay 7c> $II(78 == 7j &&x0!W
"%%goomH6M&NO GG8?@%%gook(6K&LM 	r<   c                 &    U R                  U5        g rl   ru  r   s     r=   r   FTPClientBasic.connectionLost   s    

6r<   )rr  rn  ro  rq  rw   N)r0   )r6   r7   r8   r9   r:   r   r   rn   rP   rv  rp  r   r  r  r  r  r  r  r   r;   r5   r<   r=   rl  rl  P
  sQ     EI*!0'0#$#"0H-^r<   rl  c                   *    \ rS rSrSrS rS rS rSrg)_PassiveConnectionFactoryi$  Fc                     Xl         g rl   protoInstance)rp   r  s     r=   rn   "_PassiveConnectionFactory.__init__'  s    *r<   c                 :    X R                   l        U R                   $ rl   )r  r   r  s     r=   r@  '_PassiveConnectionFactory.buildProtocol*  s    %)"!!!r<   c                 f    [        SU5      nU R                  R                  R                  U5        g )NzConnection Failed)r   r  r   r  )rp   rT  r   r[   s       r=   rU  0_PassiveConnectionFactory.clientConnectionFailed.  s)    (&1##++A.r<   r  N)	r6   r7   r8   r9   rj  rn   r@  rU  r;   r5   r<   r=   r  r  $  s    E+"/r<   r  c                       \ rS rSrSr\R                  r SS jrS r	S r
S rS rS rS	 rS
 rSS jr\rSS jr\rS rS rS rS rS rS rS rS rS rS rS rSrg)	FTPClienti3  a  
L{FTPClient} is a client implementation of the FTP protocol which
exposes FTP commands as methods which return L{Deferred}s.

Each command method returns a L{Deferred} which is called back when a
successful response code (2xx or 3xx) is received from the server or
which is error backed if an error response code (4xx or 5xx) is received
from the server or if a protocol violation occurs.  If an error response
code is received, the L{Deferred} fires with a L{Failure} wrapping a
L{CommandFailed} instance.  The L{CommandFailed} instance is created
with a list of the response lines received from the server.

See U{RFC 959<http://www.ietf.org/rfc/rfc959.txt>} for error code
definitions.

Both active and passive transfers are supported.

@ivar passive: See description in __init__.
c                 \    [         R                  U 5        U R                  X5        X0l        g)a9  
Constructor.

I will login as soon as I receive the welcome message from the server.

@param username: FTP username
@param password: FTP password
@param passive: flag that controls if I use active or passive data
    connections.  You can also change this after construction by
    assigning to C{self.passive}.
N)rl  rn   r  passive)rp   r  r  r  s       r=   rn   FTPClient.__init__J  s#     	%+r<   c                 Z    U R                   R                  5         U R                  U5        g)z=
Disconnect, and also give an error to any queued deferreds.
N)r   r  rv  rw  s     r=   rP   FTPClient.fail]  s      	%%'

5r<   c                     [         R                  " U5      n[        U[        R                  " 5       5      nU R                  X5      $ )a  
Retrieves a file or listing generated by the given command,
feeding it to the given protocol.

@param commands: list of strings of FTP commands to execute then
    receive the results of (e.g. C{LIST}, C{RETR})
@param protocol: A L{Protocol} B{instance} e.g. an
    L{FTPFileListProtocol}, or something that can be adapted to one.
    Typically this will be an L{IConsumer} implementation.

@return: L{Deferred}.
)r   	IProtocolr+  r
   r  _openDataConnection)rp   commandsr   wrappers       r=   receiveFromConnectionFTPClient.receiveFromConnectiond  s8     ''1!(ENN,<=''::r<   c                     [         R                  XU5        U R                  SSS9nUR                  U R                  5        UR                  S 5        g)zO
Login: send the username, send the password, and
set retrieval mode to binary
zTYPE Ir   r  c                     g rl   r5   r  s    r=   r  &FTPClient.queueLogin.<locals>.<lambda>  s    tr<   N)rl  r  r  r  rP   )rp   r  r  r   s       r=   r  FTPClient.queueLoginu  sE    
 	!!$(;##HQ#7	TYY	^$r<   c                 T    [        5       nU R                  X5      nUR                  U4$ )a  
XXX

@return: A tuple of two L{Deferred}s:
          - L{Deferred} L{IFinishableConsumer}. You must call
            the C{finish} method on the IFinishableConsumer when the
            file is completely transferred.
          - L{Deferred} list of control-connection responses.
)r=  r  r?  )rp   r  rK   r[  s       r=   sendToConnectionFTPClient.sendToConnection  s-     $$X1##Q''r<   c                 6  ^ ^^ U Vs/ s H  n[        USS9PM     nn[        R                  " U Vs/ s H  oUR                  PM     snSSS9nUR	                  [
        5        T R                  (       a  S/mUUU 4S jn[        S5      nT R                  U5        UR                  R                  U5      R	                  T R                  5        XhR                  TR                  /n	[        R                  " U	SSS9n
U
R	                  [
        5        T4S jnU
R                  U5        O[        S	5      nTR                  Ul        TUl        UR                  R	                  UR                  R                  5        T R                  U5        S
 Ul        S Ul	        UR	                  U4S j5        XlR                  UR                  /n	[        R                  " U	SSS9n
U
R	                  [
        5        U H  nT R                  U5        M     U
$ s  snf s  snf )z%
This method returns a DeferredList.
r0   r  T)fireOnOneErrbackconsumeErrorsNc                 l   > [        U S   SS 5      u  p[        T5      nTR                  XU5      TS'   g)z5Connect to the port specified in the response to PASVr_   rw  Nr   )r\  r  connectFactory)rw   r  r  r  _mutabler   rp   s       r=   	doPassive0FTPClient._openDataConnection.<locals>.doPassive  s:    +HRL,<=
-h7"11$a@r<   r|  c                 D    US   =(       a    US   R                  5         U $ r)  )r  )rX  ms     r=   rl  ,FTPClient._openDataConnection.<locals>.close  s    !*1*r<   r  c                     U $ rl   r5   rw  s    r=   r  /FTPClient._openDataConnection.<locals>.<lambda>  s    Fr<   c                     U $ rl   r5   )r   s    r=   r  r    s    r<   c                 6    UR                  U 5      =(       d    U $ rl   )rP   )r[   pcs     r=   r  r    s    "''!*//r<   )r   r
   DeferredListr   r  re  r  r  r  rP   r  r%  r   r  r  )rp   r  r   r  cmdsr  cmdsDeferredr  pasvCmdrN  r   rl  portCmdr  s   ` `          @r=   r  FTPClient._openDataConnection  s    >FFX'
71-XF))%)*Tc\\T*TQU
 	 12<< vHA !(Gg&((3>>tyyI#%5%5x7H7HIG""7TQUVALL*+ $  IIe
 !(G (0'8'8G$'G''(@(@(H(HIg&
 &;G".GL ##$IJ#%5%5w7O7OPG""7TQUVALL*+Cc" C G*s
   HHc                 .   [        5       nUR                  Ul        [        R                  " SU5      nX2l        U4S jnXAl        U R                  R                  5       R                  nUR                  5       R                  nS[        XV5      -   Ul
        g)z7
(Private) Generates the text of a given PORT command.
r   c                 H    UR                   (       a  UR                  5         U $ rl   )r-  r  )r   listeners     r=   listenerFail3FTPClient.generatePortCommand.<locals>.listenerFail  s    !!'')Lr<   zPORT N)rg  r   r   r  r  rP   r   r  r  r  r"  )rp   r  r   r  r  r  r  s          r=   r  FTPClient.generatePortCommand  s    " %&"++$$Q0 *2 	
 $ ~~%%',,!&&!;;r<   c                 &    UR                  SS5      $ )z;
Returns a FTP escaped path (replace newlines with nulls).

rC   )rc   rw  s     r=   
escapePathFTPClient.escapePath  s    
 ||D$''r<   c                     SU R                  U5      -   /nU(       a  UR                  SS[        U5      -   5        U R                  XB5      $ )ae  
Retrieve a file from the given path

This method issues the 'RETR' FTP command.

The file is fed into the given Protocol instance.  The data connection
will be passive if self.passive is set.

@param path: path to file that you wish to receive.
@param protocol: a L{Protocol} instance.
@param offset: offset to start downloading from

@return: L{Deferred}
zRETR r   REST )r  r  r   r  )rp   rI   r   offsetr  s        r=   retrieveFileFTPClient.retrieveFile   sE     $//$//0KKGc&k13))$99r<   c                     SU R                  U5      -   /nU(       a  UR                  SS[        U5      -   5        U R                  U5      $ )aa  
Store a file at the given path.

This method issues the 'STOR' FTP command.

@return: A tuple of two L{Deferred}s:
          - L{Deferred} L{IFinishableConsumer}. You must call
            the C{finish} method on the IFinishableConsumer when the
            file is completely transferred.
          - L{Deferred} list of control-connection responses.
zSTOR r   r  )r  r  r   r  )rp   rI   r  r  s       r=   	storeFileFTPClient.storeFile  sE     $//$//0KKGc&k13$$T**r<   c                 X  ^ ^^ T R                  ST R                  U5      -   5      nT R                  ST R                  U5      -   5      n/ m[        R                  " 5       mTR	                  U4S j5        UU 4S jnUR                  TR                  U5        UR                  T5        T$ )a  
Rename a file.

This method issues the I{RNFR}/I{RNTO} command sequence to rename
C{pathFrom} to C{pathTo}.

@param pathFrom: the absolute path to the file to be renamed
@type pathFrom: C{str}

@param pathTo: the absolute path to rename the file to.
@type pathTo: C{str}

@return: A L{Deferred} which fires when the rename operation has
    succeeded or failed.  If it succeeds, the L{Deferred} is called
    back with a two-tuple of lists.  The first list contains the
    responses to the I{RNFR} command.  The second list contains the
    responses to the I{RNTO} command.  If either I{RNFR} or I{RNTO}
    fails, the L{Deferred} is errbacked with L{CommandFailed} or
    L{BadResponse}.
@rtype: L{Deferred}

@since: 8.2
zRNFR zRNTO c                    > TU 4$ rl   r5   )
toResponsefromResponses    r=   r  "FTPClient.rename.<locals>.<lambda>J  s
    |Z.Hr<   c                 H   > TR                  5         TR                  U 5        g rl   )r  r  )r   r  rp   s    r=   ebFrom FTPClient.rename.<locals>.ebFromL  s      "NN7#r<   )r  r  r
   r  r  r  r  chainDeferred)rp   pathFrompathTo
renameFromrenameTor  r  r  s   `     @@r=   r  FTPClient.rename)  s    0 ,,Wtx7P-PQ
**7T__V5L+LM !HI	$ 	 3 3V< 	v&r<   c                 V    Uc  SnU R                  SU R                  U5      -   /U5      $ )a<  
Retrieve a file listing into the given protocol instance.

This method issues the 'LIST' FTP command.

@param path: path to get a file listing for.
@param protocol: a L{Protocol} instance, probably a
    L{FTPFileListProtocol} instance.  It can cope with most common file
    listing formats.

@return: L{Deferred}
rA   zLIST r  r  rp   rI   r   s      r=   rS  FTPClient.listY  s2     <D))7T__T5J+J*KXVVr<   c                 V    Uc  SnU R                  SU R                  U5      -   /U5      $ )a  
Retrieve a short file listing into the given protocol instance.

This method issues the 'NLST' FTP command.

NLST (should) return a list of filenames, one per line.

@param path: path to get short file listing for.
@param protocol: a L{Protocol} instance.
rA   zNLST r  r  s      r=   nlstFTPClient.nlstj  s2     <D))7T__T5J+J*KXVVr<   c                 H    U R                  SU R                  U5      -   5      $ )zk
Issues the CWD (Change Working Directory) command.

@return: a L{Deferred} that will be called when done.
zCWD r  r  rw  s     r=   rH   FTPClient.cwdy  s#     &&v0E'EFFr<   c                 H    U R                  SU R                  U5      -   5      $ )a  
Make a directory

This method issues the MKD command.

@param path: The path to the directory to create.
@type path: C{str}

@return: A L{Deferred} which fires when the server responds.  If the
    directory is created, the L{Deferred} is called back with the
    server response.  If the server response indicates the directory
    was not created, the L{Deferred} is errbacked with a L{Failure}
    wrapping L{CommandFailed} or L{BadResponse}.
@rtype: L{Deferred}

@since: 8.2
zMKD r
  rw  s     r=   r  FTPClient.makeDirectory  #    $ &&v0E'EFFr<   c                 H    U R                  SU R                  U5      -   5      $ )a  
Delete a file on the server.

L{removeFile} issues a I{DELE} command to the server to remove the
indicated file.  Note that this command cannot remove a directory.

@param path: The path to the file to delete. May be relative to the
    current dir.
@type path: C{str}

@return: A L{Deferred} which fires when the server responds.  On error,
    it is errbacked with either L{CommandFailed} or L{BadResponse}.  On
    success, it is called back with a list of response lines.
@rtype: L{Deferred}

@since: 8.2
zDELE r
  rw  s     r=   r  FTPClient.removeFile  s#    $ &&w1F'FGGr<   c                 H    U R                  SU R                  U5      -   5      $ )a   
Delete a directory on the server.

L{removeDirectory} issues a I{RMD} command to the server to remove the
indicated directory. Described in RFC959.

@param path: The path to the directory to delete. May be relative to
    the current working directory.
@type path: C{str}

@return: A L{Deferred} which fires when the server responds. On error,
    it is errbacked with either L{CommandFailed} or L{BadResponse}. On
    success, it is called back with a list of response lines.
@rtype: L{Deferred}

@since: 11.1
zRMD r
  rw  s     r=   r  FTPClient.removeDirectory  r  r<   c                 $    U R                  S5      $ )zg
Issues the CDUP (Change Directory UP) command.

@return: a L{Deferred} that will be called when done.
CDUPr  rv   s    r=   cdupFTPClient.cdup  s     &&v..r<   c                 $    U R                  S5      $ )a0  
Issues the PWD (Print Working Directory) command.

The L{getDirectory} does the same job but automatically parses the
result.

@return: a L{Deferred} that will be called when done.  It is up to the
    caller to interpret the response, but the L{parsePWDResponse}
    method in this module should work.
PWDr  rv   s    r=   rN  FTPClient.pwd  s     &&u--r<   c                 F    S nU R                  5       R                  U5      $ )z
Returns the current remote directory.

@return: a L{Deferred} that will be called back with a C{str} giving
    the remote directory or which will errback with L{CommandFailed}
    if an error response is returned.
c                 *    [        U S   R                  SS5      S   5      S:w  a  [        e [        U S   5      nUc  [        R
                  " [        U 5      5      $ U$ ! [        [        4 a"    [        R
                  " [        U 5      5      s $ f = f)Nr   r  r0   i  )r  rE   r  
IndexErrorr   rz  r  parsePWDResponse)r  rI   s     r=   cbParse'FTPClient.getDirectory.<locals>.cbParse  s    >vaysA.q12c9$$ : $F1I.D|}V'<==K 
+ >}V'<==>s   +A   /BB)rN  r  )rp   r  s     r=   getDirectoryFTPClient.getDirectory  s     
	 xxz%%g..r<   c                 $    U R                  S5      $ )z
Issues the I{QUIT} command.

@return: A L{Deferred} that fires when the server acknowledges the
    I{QUIT} command.  The transport should not be disconnected until
    this L{Deferred} fires.
rz  r  rv   s    r=   quitFTPClient.quit  s     &&v..r<   )r  N)r  ztwisted@twistedmatrix.comr0   )r   ) r6   r7   r8   r9   r:   r   r9  r  rn   rP   r  r  r  r  r  r  r  retrr  storr  rS  r  rH   r  r  r  r  rN  r!  r$  r;   r5   r<   r=   r  r  3  s    ( ''N ST&;"
%(EN!<F(:( D+" D.`W"WGG(H(G(/././r<   r  c                   b    \ rS rSrSr\R                  " S5      rSrSr	S r
S rS rS	 rS
 rSrg)FTPFileListProtocoli  a[  
Parser for standard FTP file listings

This is the evil required to match::

    -rw-r--r--   1 root     other        531 Jan 29 03:26 README

If you need different evil for a wacky FTP server, you can
override either C{fileLinePattern} or C{parseDirectoryLine()}.

It populates the instance attribute self.files, which is a list containing
dicts with the following keys (examples from the above line):
    - filetype:   e.g. 'd' for directories, or '-' for an ordinary file
    - perms:      e.g. 'rw-r--r--'
    - nlinks:     e.g. 1
    - owner:      e.g. 'root'
    - group:      e.g. 'other'
    - size:       e.g. 531
    - date:       e.g. 'Jan 29 03:26'
    - filename:   e.g. 'README'
    - linktarget: e.g. 'some/file'

Note that the 'date' value will be formatted differently depending on the
date.  Check U{http://cr.yp.to/ftp.html} if you really want to try to parse
it.

It also matches the following::
    -rw-r--r--   1 root     other        531 Jan 29 03:26 I HAVE\ SPACE
       - filename:   e.g. 'I HAVE SPACE'

    -rw-r--r--   1 root     other        531 Jan 29 03:26 LINK -> TARGET
       - filename:   e.g. 'LINK'
       - linktarget: e.g. 'TARGET'

    -rw-r--r--   1 root     other        531 Jan 29 03:26 N S -> L S
       - filename:   e.g. 'N S'
       - linktarget: e.g. 'L S'

@ivar files: list of dicts describing the files in this listing
z^(?P<filetype>.)(?P<perms>.{9})\s+(?P<nlinks>\d*)\s*(?P<owner>\S+)\s+(?P<group>\S+)\s+(?P<size>\d+)\s+(?P<date>...\s+\d+\s+[\d:]+)\s+(?P<filename>.{1,}?)( -> (?P<linktarget>[^\r]*))?\r?$   
r   c                     / U l         g rl   filesrv   s    r=   rn   FTPFileListProtocol.__init__'  s	    
r<   c                     UR                  U R                  5      nU R                  U5      nUc  U R                  U5        g U R	                  U5        g rl   )r  r   parseDirectoryLineunknownLineaddFile)rp   r   r   s      r=   r   FTPFileListProtocol.lineReceived*  sB    {{4>>*##D)9T"LLOr<   c                    U R                   R                  U5      nUc  gUR                  5       nUS   R                  SS5      US'   [	        US   5      US'   [	        US   5      US'   US   (       a  US   R                  SS5      US'   U$ )z
Return a dictionary of fields, or None if line cannot be parsed.

@param line: line of text expected to contain a directory entry
@type line: str

@return: dict
Nfilenamez\ r  nlinksr   
linktarget)fileLinePatternr  	groupdictrc   r  )rp   r   r  r   s       r=   r0  &FTPFileListProtocol.parseDirectoryLine2  s     $$**40=!AjM11%=AjMak*AhKAfIAfI"#L/"9"9%"E,Hr<   c                 :    U R                   R                  U5        g)aA  
Append file information dictionary to the list of known files.

Subclasses can override or extend this method to handle file
information differently without affecting the parsing of data
from the server.

@param info: dictionary containing the parsed representation
             of the file information
@type info: dict
N)r-  rG   )rp   r   s     r=   r2  FTPFileListProtocol.addFileG  s     	

$r<   c                     g)z
Deal with received lines which could not be parsed as file
information.

Subclasses can override this to perform any special processing
needed.

@param line: unparsable line as received
@type line: str
Nr5   r   s     r=   r1  FTPFileListProtocol.unknownLineU  s     	r<   r,  N)r6   r7   r8   r9   r:   rS  compiler8  	delimiterr   rn   r  r0  r2  r1  r;   r5   r<   r=   r)  r)    sB    'R jj	-O II* r<   r)  c                 f    [         R                  " SU 5      nU(       a  UR                  5       S   $ g)z
Returns the path from a response to a PWD command.

Responses typically look like::

    257 "/home/andrew" is current directory.

For this example, I will return C{'/home/andrew'}.

If I can't find the path, I return L{None}.
z"(.*)"r   N)rS  searchgroups)rw   r  s     r=   r  r  c  s+     IIh)E||~a  r<   rl   )r[  )r:   rN   r`   r  r]  rS  r  r   rQ  rN  ImportErrorzope.interfacer   r   twistedr   twisted.credr   r   r   r  r	   r4  r
   r   r   r   twisted.protocolsr   r   twisted.pythonr   r   r   RESTART_MARKER_REPLYSERVICE_READY_IN_N_MINUTESrL  r  r  r  r+  r!  CMD_NOT_IMPLMNTD_SUPERFLUOUSSYS_STATUS_OR_HELP_REPLYr  
DIR_STATUSr  HELP_MSGr  SVC_READY_FOR_NEW_USERr  SVC_CLOSING_CTRL_CNXr   DATA_CNX_OPEN_NO_XFR_IN_PROGRESSCLOSING_DATA_CNXrM  r  r#  r  r  rb  rl  r  r  r  NEED_ACCT_FOR_LOGINr  SVC_NOT_AVAIL_CLOSING_CTRL_CNXrs  r2  r{  REQ_ACTN_ABRTD_FILE_UNAVAILREQ_ACTN_ABRTD_LOCAL_ERRREQ_ACTN_ABRTD_INSUFF_STORAGEr   r   r   r  r   r   r   r   r  r   NEED_ACCT_FOR_STORrz   r   r}   r   r  r   r   PAGE_TYPE_UNKEXCEEDED_STORAGE_ALLOCFILENAME_NOT_ALLOWEDrt   r  r"  rm   r3   rL   r\   ra   rb   rh   rj   rQ   r|   rT   rV   rX   rZ   r   r   r   r   r   r   r   r   r   r   r   r   	IConsumerrD  r   ClientFactoryr.  rZ  rd  r  rq  TimeoutMixinrv  r!  r  r  rC  rH  rY  rn  rp  r  r  r  IRealmr  r	  r  r  r  r  r  r  r   r+  r8  r=  r\  r  rB  re  ServerFactoryrg  rl  r  r  r)  r  r5   r<   r=   <module>rb     s  

    	 	   2  K K H H - 1 1
  " "' $ 	 $ " 

   #(       ! " 		 "  %* "!(    #    % 
   # " $       R .R  A	R
 $ &R ! #R R &R R "R ! #R  7!R" oy)#R$ %R& 'R( n)R* &+R, -R. //R0 E1R2 3R4 % '5R8 ,9R: .;R< 9=R@ FARB 8CRD TERH  KIRJ zKRL !MRP :QRR  SRV 6WRX ' )YR^ # %_Rb  cRf 9gRh PiRj  !UkRl  !mRp " $qRv &wRx =yRz 8{R| <}R~ TR@ <ARB  LCRF !"PGRH 9IRJ 5KRL BMRN 83U<&&<* 'TcRv 	
) 2$ $$V, B<) <  !+ !"K "; k  [ # #![ !+; +*+ *	y 		) 	+  -k -8" Z!!"K'(

 K' #K'\]/'' ]/FB B" Z!!"  #.(%,, (Y$%

h33 Y$x&@66 &@X}	 }@	 " 2$5p Yp p pf Y  $R0  R0j Z# # # V]]Y Y YD-| -,'\ 'J	X 		H 		( 		 		X 	
+ 
+%h'' %"
*.. 
  !)(X&& )( ")(X"
	%$
// &QU'' Qh/ 6 6 /~/ ~/Bl%,, l^]j  C#s   S 
S+*S+