Ϫfp dZddlZddlZddlZddlZddlZddlZ ddlZddlZddl m Z m Z ddl mZddlmZmZmZmZddlmZmZmZmZmZddlmZmZddlmZmZm Z d Z!d Z"d Z#d Z$d Z%dZ&dZ'dZ(dZ)dZ*dZ+dZ,dZ-dZ.dZ/dZ0dZ1dZ2dZ3dZ4dZ5dZ6dZ7d Z8d!Z9d"Z:d#Z;d$Zd'Z?d(Z@d)ZAd*ZBd+ZCd,ZDd-ZEd.ZFd/ZGd0ZHd1ZId2ZJd3ZKd4ZLd5ZMd6ZNd7ZOd8ZPd9ZQd:ZRd;ZSdZVd?ZWd@ZXdAZYdBZZie!dCe"dDe#dEe$dFe%dGe&dHe'dIe(dJe)dKe*dLdMge+dNe,dOe-dPe.dQe0dRe/dSe1dTie2dUe3dVe4dWe5dXe6dYe7dZe8d[e9d\e:d]e;d^edae?dbe@dceAddeBdeieCdfeDdgeEdheFdieGdjeHdkeIdleJdmeKdneLdoeMdpeNdqeOdrePdseQdteRdueSdveTdweVdxeWdyeUdzeXd{eYd|eZd}iZ[Gd~de\Z]dZ^dZ_ejdZaddZbGdde\ZcGddecZdGddecZeGddecZfGddecZgGddecZhGddecZiGddecZjGddecZkGddecZlGddecZmGdde\ZnGdde\ZoGddecZpGddecZqdZrgdZse ejGddejZvGddejZxGddZye ejGddZzGddejZ|GddejejZ~GddejZGdde ZGdde ZGdde ZdZddZe eGddZe eGddZGddeZe eGddZe ejGd„dëZGdĄdeZGdƄdeZGdȄdenZGdʄdenZGd̄denZGd΄denZGdЄdenZGd҄dӫZGdԄdejZGdքdejZe eGd؄dejZdڄZdۄZd܄ZGd݄dej4ZGd߄dejZGddejZGddeZGddejZdZy#e $rdxZZYwxYw)z An FTP protocol implementation N) Interface implementer) copyright)checkers credentialserrorportal)deferr interfacesprotocolreactor)basicpolicies)failurefilepathlog100120125150z200.1z200.2z200.3202z211.1z211.2212213214215z220.1z220.2z221.1z221.2225z226.1z226.2227229z230.1z230.2250z257.1z257.2z331.1z331.2332350z421.1z421.2425426450451452500501z502.1z502.2503504z530.1z530.2532z550.1z550.2z550.3z550.4z550.5z550.6z550.7551552553z110 MARK yyyy-mmmmz120 service ready in %s minutesz3125 Data connection already open, starting transferz4150 File status okay; about to open data connection.z200 Command OKz200 Type set to %s.z 200 PORT OKz5202 Command not implemented, superfluous at this sitez211 System status replyz 211-Features:z211 Endz212 %sz213 %sz 214 help: %sz215 UNIX Type: L8z220 %sz220 Service readyz&221 Service closing control connectionz 221 Goodbye.z1225 data connection open, no transfer in progressz226 Abort successfulz226 Transfer Complete.z227 Entering Passive Mode (%s).z,229 Entering Extended Passive Mode (|||%s|).z230 User logged in, proceedz2230 Anonymous login ok, access restrictions apply.z&250 Requested File Action Completed OKz257 "%s"z257 "%s" createdz331 Password required for %s.z8331 Guest login ok, type your email address as password.z332 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.z425 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.z500 Syntax error: %sz#501 syntax error in argument(s) %s.z 502 Command '%s' not implementedz 502 Option '%s' not implemented.z&503 Incorrect sequence of commands: %sz'504 Not implemented for parameter '%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.z550 %s: Permission denied.z:550 Anonymous users are forbidden to change the filesystemz%550 Cannot rmd, %s is not a directoryz550 %s: File existsz550 %s: is a directoryz"550 Requested action not taken: %sz551 Page type unknownzC552 Requested file action aborted, exceeded file storage allocationz5553 Requested action not taken, file name not allowedceZdZdZy) InvalidPathzL Internal exception used to signify an error during parsing a path. N)__name__ __module__ __qualname____doc__7/usr/lib/python3/dist-packages/twisted/protocols/ftp.pyr0r0sr6r0c |jdrg}n|dd}|jdD]V}|dk(s|dk(r|dk(r|r|j&t||d|vsd|vr t|||j |X|S)zn Normalize a path, as represented by a list of strings each representing one segment of the path. /N...) startswithsplitpopr0append)cwdpathsegsss r7 toSegmentsrFs  s1v ZZ_  8qBw  $Y !#t,, QY#(c4( ( KKN  Kr6c:|tjk(rtjt |S|tj k(s|tj k(rtjt|S|tjk(rtjt|S|tjk(rtjt|S|tjk(rtjt|StjS)z? Map C{OSError} and C{IOError} to standard FTP errors. )errnoENOENTr failFileNotFoundErrorEACCESEPERMPermissionDeniedErrorENOTDIRIsNotADirectoryErrorEEXISTFileExistsErrorEISDIRIsADirectoryError)erCs r7errnoToFailurerVs ELLzz+D122 ell a5;;.zz/566 emm zz.t455 ell zz/$/00 ell zz+D122zz|r6TESTcx|sy|d}tj|}tjd|d}||k(ryy)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. FrWT)fnmatch translate_testTranslationreplace)segments globCandidateglobTranslationsnonGlobTranslationss r7_isGlobbingExpressionrcsJ RLM((7*226=!L..r6ceZdZdZdZdZy) FTPCmdErrorz- Generic exception for FTP commands. c>tj|g|||_yN) Exception__init__ errorMessage)selfmsgs r7rizFTPCmdError.__init__s4&#&r6cBt|j|jzS)zA Generate a FTP response message for this error. )RESPONSE errorCoderjrks r7responsezFTPCmdError.responses'$*;*;;;r6N)r1r2r3r4rirqr5r6r7rere s .formatDatesd++-C .}}  ,, D{{emm+6==DtKKr6zY%(directory)s%(permissions)s%(hardlinks)4d %(owner)-9s %(group)-9s %(size)15d %(date)12s d-N) directory permissions hardlinksownergroupsizedate) shorthandrrencode _encoding) rknamerrrrmodifiedrrrformatrls r7_formatOneListResponsezDTP._formatOneListResponses* L =  &.35#*446&rr"4;;x#89  &  Tzr6cH|j|j|g|yrg)rr)rkrrqs r7sendListResponsezDTP.sendListResponses! 1d11$BBCr6c:|jj||SrgrregisterProducerrkproducer streamings r7rzDTP.registerProducers~~..xCCr6cl|jj|jjyrg)runregisterProducerloseConnectionrps r7rzDTP.unregisterProducers" ))+ %%'r6cf|jr|jj|Std)NzCrap damn crap damn crap damn)rrrrhrkdatas r7rz DTP.writes,   >>''- -788r6c |jj|y#t$r|jj YywxYwrg)_consr BaseExceptionrerrbackrkbytess r7 _conswritezDTP._conswrites: ' JJ  U # '    $ $ & 's#AAcv|j|j|y|jj|yrg)rrrrArs r7 dataReceivedzDTP.dataReceiveds* :: ! OOE " LL   &r6cL|jjd|_|`|Srg)rrrrkignoreds r7_unregConsumerzDTP._unregConsumer s$ %%'  r6c|jJ||_|jj|d|jD]}|j|d|_|jr8t j x|_}|j|j|S|jjd|_t jdSr) rrrrrr DeferredraddBothrrsucceed)rkconschunkrs r7registerConsumerzDTP.registerConsumerszz!!!  ##D$/\\ #E OOE " #   #(>>#3 3D q IId)) *H JJ ) ) +DJ==& &r6c8|jjyrg)rresumeProducingrps r7r zDTP.resumeProducing#s &&(r6c8|jjyrg)rpauseProducingrps r7r zDTP.pauseProducing& %%'r6c8|jjyrg)r stopProducingrps r7rzDTP.stopProducing)s $$&r6)r1r2r3rrrrrrrrrrrrrrrrrr r rr5r6r7rrsiK EKGI , -4lDD(9 ' '  ' )('r6rcneZdZdZeZeZeZeZdZ d dZ dZ dZ dZ dZd Zd Zy) DTPFactorya 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~||_||_tj|_d|_|ddlm}||_y)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 Nrr ) pipeerHostr rr delayedCalltwisted.internetr _reactor)rkrrr s r7rizDTPFactory.__init__Ns7  (  ? 0 r6ctjdd|j|jury|j|_|j t }||_|j|_||j_ |S)NzDTPFactory.buildProtocolTr) rrl_state _IN_PROGRESS _FINISHED cancelTimeoutrrr dtpInstancerkaddrps r7 buildProtocolzDTPFactory.buildProtocol_sg *$7 ;;d// /nn   E wwr6cRtjdd|jy)NzdtpFactory.stopFactoryTr)rrlrrps r7 stopFactoryzDTPFactory.stopFactoryms (5 r6ctjd|j|jury|j|_|j }d|_|j ttjdy)Nz$timed out waiting for DTP connectionzDTPFactory timeout) rrlrr_FAILEDrrrr TimeoutError)rkrs r7timeoutFactoryzDTPFactory.timeoutFactoryqs] 67 ;;d// / ll MM  %e&8&89M&NOPr6c|jM|jjr2tjdd|jj yyy)Nzcancelling DTP timeoutTr)ractiverrlcancelrps r7rzDTPFactory.cancelTimeout{sI    'D,<,<,C,C,E GG,D 9    # # %-F 'r6ctjd|z|jj||j|_y)Nz'DTPFactory.setTimeout set to %s seconds)rrlr callLaterr(r)rksecondss r7 setTimeoutzDTPFactory.setTimeouts3 9GCD==227Dr>sr6r>ceZdZdZdZdZy)FTPOverflowProtocolz:FTP mini-protocol for when there are too many connections.rc|jttj|j|j j yrg)rrnTOO_MANY_CONNECTIONSrrrrrps r7rz"FTPOverflowProtocol.connectionMades3 h34;;DNNKL %%'r6N)r1r2r3r4rrr5r6r7rGrGsDI(r6rGceZdZdZdZed\ZZZZ dZ dZ dZ dZ dZdZdZddgZgd Zed d Zej*Zd Zd ZfdZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$d4dZ%dZ&dZ'dZ(dZ)dZ*d Z+d!Z,d"Z-d#Z.d$Z/d%Z0d&Z1d'Z2d(Z3d)Z4d*Z5d+Z6d,Z7d-Z8d.Z9d/Z:d0Z;d1ZxZ?S)5FTPa; 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 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 NTFEATQUIT)rNMDTMPASVSIZEzTYPE A;IrrZrc>t||z}|j|yrg)rnr)rkkeyargsrls r7replyz FTP.replyssmd" cr6czt|tr|j|j}t||y)za (Private) Encodes and sends a line @param line: L{bytes} or L{unicode} N) isinstancerrrsuperr)rkr __class__s r7rz FTP.sendLines. dC ;;t~~.D r6c|j|_|j|j|j t |j jyrg)UNAUTHstater/timeOutrV WELCOME_MSGrwelcomeMessagerps r7rzFTP.connectionMades5[[   % ; ; ;->-J JJ    r6c8|jjyrgrrrps r7timeoutConnectionzFTP.timeoutConnectionr r6c jjttk7r|j j } fd}fd}fd}|j d}|dk7r|d| ||dzdf}n| d}tjj g|}|j|||jtjdd lm}|j d|j"|y) Ncjtr*jjj yjt r.t fddDrjtdytjdtjjtdy)Nc3TK|]}|jjdv!yw)rN)valuerU).0rlerrs r7 z:FTP.lineReceived..processFailed..#s+.syy~~a((.s%()z takes exactlyzrequired positional argumentz requires an argument.zUnexpected FTP errorzinternal server error) checkrerrmrq TypeErroranyrVrrrlroREQ_ACTN_NOT_TAKEN)rocmdrks`r7 processFailedz'FTP.lineReceived..processFailed syy% cii00239%#.L.+ :#.D'EF./  -/FGr6cnt|trj|y|j|yyrg)rXtuplerVresultrks r7processSucceededz*FTP.lineReceived..processSucceeded-s2&%( F## 6"$r6c@jsjyyrg) disconnectedr )rrks r7allDonez!FTP.lineReceived..allDone3s$$$$&%r6 rYrZr5rr) resetTimeoutr rrdecoderfindr maybeDeferredprocessCommand addCallbacks addErrbackrrorr r-r) rkrrvr{r~ spaceIndexrUrr rus ` @r7 lineReceivedzFTP.lineReceiveds   C<;;t~~.D H #  'YYs^  { #Ca)*,DCD    3 3S @4 @ '7 SWW -!QYY0r6cfd}|j}|jvr||Sjjk(r'|dk(rjS|dk(rt dfSt Sjjk(r|dk(rjSt dfSjjk(r||Sjjk(r|dk(rjSt dfSy)Ncntd|zd}||Stjt|S)Nftp_)getattrr rJr)commandmethodparamsrks r7call_ftp_commandz,FTP.processCommand..call_ftp_commandJs;T6G#3T:F!v&::4W=> >r6USERPASSzUSER required before PASSzPASS required after USERRNTOzRNTO required after RNFR) upperPUBLIC_COMMANDSr]r\ftp_USERr NOT_LOGGED_ININAUTHftp_PASSAUTHEDRENAMINGftp_RNTO)rkrurrs` ` r7rzFTP.processCommandIs ? iik $&& &#C( ( ZZ4;; &f}$t}}f--"$???$$ ZZ4;; &f}$t}}f--"$>>> ZZ4;; &#C( ( ZZ4== (f}$t}}f--"$>>> )r6c|jD]} |j||}|cStjdd|j#tj$rYTwxYw)ze Return a port for passive access, using C{self.passivePortRange} attribute. r;zNo port available in range )passivePortRange listenFactoryrCannotListenError)rkrportndtpPorts r7 getDTPPortzFTP.getDTPPortls| ** E ,,UG<  %% 4T5J5J4KL  **  sA  A"!A"c|stjtdS||_|j|_|j jr)|j|j jk(rtSt|fS)zc First part of login. Get the username the peer wants to authenticate as. zUSER requires an argument) r rJr_userrr]rallowAnonymous userAnonymousGUEST_NAME_OK_NEED_EMAILUSR_NAME_OK_NEED_PASS)rkusernames r7rz FTP.ftp_USER|sa ::n-HIJ J [[ << & &4::9S9S+S+ +)84 4r6c~jjr>jjjk(rt j }t n&t jj|}t`fd}fd}jj|dt}|j|||S)zf Second part of login. Get the password the peer wants to authenticate with. c~|\}}}|tusJd|_|_g_j_S)NzThe realm is busted, jerk.) IFTPShellrfrbworkingDirectoryrr])rz interfaceavatarrbrVrks r7_cbLoginzFTP.ftp_PASS.._cbLoginsI*0 'Y ) G+G G)DJ DK$&D !DJLr6c|jtjtjj_t rg)trap cred_errorUnauthorizedLoginUnhandledCredentialsr\r]r)rrks r7_ebLoginzFTP.ftp_PASS.._ebLogins0 GLL55z7V7V WDJ$ $r6N) rrrrr AnonymousGUEST_LOGGED_IN_PROCEEDUsernamePasswordUSR_LOGGED_IN_PROCEEDr loginrr)rkpasswordcredsrrrrVs` @r7rz FTP.ftp_PASSs << & &4::9S9S+S))+E+E 00XFE)E J  % KK  eT9 5 x*r6c|j|jt||_|jj|j|j |j|_|jjj}|j jj}|jtt|||jjjdS)a 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. )rcyrgr5igns r7zFTP.ftp_PASV..r6)rcrdrr/ dtpTimeoutrrrgetHosthostportrVENTERING_PASV_MODEencodeHostPortr addCallback)rkrrs r7ftp_PASVz FTP.ftp_PASVs ?? & OO $- ""4??3t7 ~~%%',,||##%** %~dD'AB''334DEEr6cttt|jd}dt|ddz}|ddz|dz}|j|j t ||jjj|_|jj|jtj|||j|_d}d}|jjj!||S) N,z %d.%d.%d.%drLr)rrctSrg)ENTERING_PORT_MODE)rs r7 connectedzFTP.ftp_PORT..connecteds% %r6c8|jttSrg)rrCANT_OPEN_DATA_CNXros r7 connFailedz FTP.ftp_PORT..connFaileds HH( )% %r6)rxmapintr?rcrdrrgetPeerrr/rr connectTCPrrr)rkaddressr iprrrs r7ftp_PORTz FTP.ftp_PORTsSgmmC012 U48_ ,Aw!|d1g% ?? & OO $t~~7M7M7O7T7TU ""4??3))"dDOOD  & &''44Y KKr6cHt|tr|jdS|S)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}:: 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 = raw = 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} zutf-8)rXrr)rkrs r7 _encodeNamezFTP._encodeNames"6 dC ;;w' ' r6cjjjstjt dS|j dvrd}fd} t j|}jj|d}|j||S#t$r!tjt|cYSwxYw)aThis 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-alr;cjt|D]2\}}j|}jj ||4jj j tfSrg)rVDATA_CNX_ALREADY_OPEN_START_XFRrrrrrTXFR_COMPLETE_OK)resultsrattrsrks r7 gotListingz FTP.ftp_LIST..gotListingsl JJ6 7& ? e''-  11$> ?    & & 5 5 7$& &r6)rrrrrrr) rrr rJrlowerrFrr0rKrflistr)rkrCrr_rs` r7ftp_LISTz FTP.ftp_LISTs    #4+;+;+G+G::12VWX X ::<5 5D ' 7!$"7"7>H JJOO    j!! 7::/56 6 7sB!!'C  C cjjjstjt dS t j |}fd}fd}t|r|j}nd}jj|}|j|||j||S#t$r!tjt|cYSwxYw)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. Nrc(jt|D]M\}}|r|s tj||s"j|}jj |Ojj jtfS)a 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} ) rVrr[rrrrrr)rglobrrrks r7cbListzFTP.ftp_NLST..cbListCs~$ JJ6 7!( 4 gt)D++D1D$$--d3 4    & & 5 5 7$& &r6cZjjjtfS)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} )rrrr)rrks r7listErrzFTP.ftp_NLST..listErr]s&    & & 5 5 7$& &r6)rrr rJrrFrr0rKrcr@rfrrr)rkrCr_rrrrs` r7ftp_NLSTz FTP.ftp_NLST+s    #4+;+;+G+G::12VWX X 7!$"7"7>H '4 '" ! *<<>DD JJOOH % fd# Ws 7::/56 6 7sC'C+*C+c tj|fd}j jj|S#t$r!tjt |cYSwxYw)Nc _tfSrg)rREQ_FILE_ACTN_COMPLETED_OK)rzr_rks r7 accessGrantedz"FTP.ftp_CWD..accessGranteds$,D !.0 0r6) rFrr0r rJrKrfaccessr)rkrCrr_s` @r7ftp_CWDz FTP.ftp_CWD{sg 7!$"7"7>H  1zz  *66}EE 7::/56 6 7sA 'A43A4c$|jdS)Nr<)rrps r7ftp_CDUPz FTP.ftp_CDUPs||D!!r6cJtddj|jzfS)Nr9) PWD_REPLYjoinrrps r7ftp_PWDz FTP.ftp_PWDs!3$*?*?!@@AAr6c j td tj| jdfd}jstjn jddfd} fd}jj }|j|||j||S#t$r!t j t|cYSwxYw)a 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 or PASV required before RETRcRjjj|Srgr/rr^rys r7 enableTimeoutz#FTP.ftp_RETR..enableTimeout OODLL00 1Mr6ctfSrgrrzs r7cbSentzFTP.ftp_RETR..cbSents $& &r6ctjdtj||jtr|St fS)Nz7Unexpected error attempting to transmit file to client:)rrlrorqreCNX_CLOSED_TXFR_ABORTEDrs r7ebSentzFTP.ftp_RETR..ebSents4 GGM N GGCLyy% +- -r6cjjrjtnjt|j }|j |Srg)rrrVrFILE_STATUS_OK_OPEN_DATA_CNXsendr)filerrrr rks r7cbOpenedzFTP.ftp_RETR..cbOpenedsL++ :; 78 $A NN66 *Hr6c<|jttts*t j dt j ||jtr'|jjdjfStdjfS)Nz:Unexpected error attempting to open file for transmission:r9) rqrNrKrTrrlrorermrorrsronewsegss r7ebOpenedzFTP.ftp_RETR..ebOpenedsp99%'8:KWX yy% ++SXXg->??"CHHW$56 6r6)rrrFrr0r rJrKr/binaryr6rfopenForReadingrr) rkrCrrrrrrr rs ` @@@@r7ftp_RETRz FTP.ftp_RETRs    #%&IJ J 7 !6!6=G   {{'(8(89D##D ' .  7 JJ % %g . x* - o 7::/56 6 7sC 'C54C5c j td tj| jdfd}fd} fd}fdddjj }|j|||j||S#t$r!t j t|cYSwxYw) 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 or PASV required before STORcRjjj|Srgrrys r7rz#FTP.ftp_STOR..enableTimeoutrr6cj}|j|jfd|j|S)zx File was open for reading. Launch the data transfer channel via the file consumer. c$jSrg)rD)rr s r7rz0FTP.ftp_STOR..cbOpened..s $**,r6)receiverr)r r cbConsumerrr s` r7rzFTP.ftp_STOR..cbOpeneds<  A MM* % MM6 7 NN66 *Hr6ct|jtr'|jjdj fSt j |dtdj fS)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. r9z-Unexpected error received while opening file:)rXrmrerorrrorsrs r7rzFTP.ftp_STOR..ebOpenedsT#))[1 ++SXXg->?? GGCH I"CHHW$56 6r6cjs t|}jj|}jjrj t |Sj t|S)z Called after the file was opended for reading. Prepare the data transfer channel and send the response to the command channel. )rr6rrrrVrr )rrrks r7rz FTP.ftp_STOR..cbConsumer se;;+D1  11$7A++ :;H 78Hr6ctfS)zK Called from data transport when transfer is done. rrs r7rzFTP.ftp_STOR..cbSent!s %& &r6cjtj|d|jtr|StfS)zk Called from data transport when there are errors during the transfer. z*Unexpected error received during transfer:)rrorqrerrs r7r zFTP.ftp_STOR..ebSent's- GGCE Fyy% +- -r6) rrrFrr0r rJrKr/rfopenForWritingrr) rkrCrrrrrrr rs ` @@@@r7ftp_STORz FTP.ftp_STORs    #%&IJ J 7 !6!6=G    7 ( '  . JJ % %g . x* - [ 7::/56 6 7sB!!'C  C c t|j|}d}|j j|dj|S#t$r!tjt |cYSwxYw)ab 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,|\}tt|fSrg) FILE_STATUSr)rzrs r7cbStatzFTP.ftp_SIZE..cbStatWsGTT+ +r6)r rFrr0r rJrKrfstatrrkrCrr%s r7ftp_SIZEz FTP.ftp_SIZE8sf4 7 !6!6=G ,zzw 2>>vFF 7::/56 6 7A'A0/A0c t|j|}d}|j j|dj|S#t$r!tjt |cYSwxYw)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 ch|\}ttjdtj|fS)Nz %Y%m%d%H%M%S)r$rstrftimer)rzrs r7r%zFTP.ftp_MDTM..cbStatos( KX~t{{8?T!UV Vr6)rr&r(s r7ftp_MDTMz FTP.ftp_MDTM]sg 7 !6!6=G Wzzw 6BB6JJ 7::/56 6 7r*c|j}|r1t|d|dzd}| ||ddS|j|StfS)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 (Space, ASCII code 32). type_rNrZ)rr type_UNKNOWNr)rktyper!fs r7ftp_TYPEz FTP.ftp_TYPEusU JJL g!nd3A}12x$$Q' '}r6cv|dk(s|dk(rd|_td|zfStjt |S)Nr;NFAr TYPE_SET_OKr rJrrkcodes r7type_Az FTP.type_As: 2:DKt, ,::/56 6r6cf|dk(rd|_tdfStjt |S)Nr;TIr8r:s r7type_Iz FTP.type_Is0 2:DK% %::/56 6r6c>tjt|Srg)r rJrr:s r7r1zFTP.type_UNKNOWNszz6t<==r6ctSrg) NAME_SYS_TYPErps r7ftp_SYSTz FTP.ftp_SYSTsr6cv|j}|dk(rtfStjt |S)NFrCMD_OKr rJr)rk structurer!s r7ftp_STRUz FTP.ftp_STRUs2 OO  89 zz6yABBr6cv|j}|dk(rtfStjt |S)NSrF)rkmoder!s r7ftp_MODEz FTP.ftp_MODEs1 JJL 89 zz6t<==r6c t|j}|j j|jfdS#t$r!tjt cYSwxYw)NctfSrg) MKD_REPLY)rrCs r7rzFTP.ftp_MKD..s D)r6) rFrr0r rJrKrf makeDirectoryrrkrCrs ` r7ftp_MKDz FTP.ftp_MKDsg 7 !6!6=Gzz''0<< )   7::/56 6 7sA'A0/A0c t|j|}|j j|jdS#t$r!tjt |cYSwxYw)NctfSrgrrs r7rzFTP.ftp_RMD.. 35r6) rFrr0r rJrKrfremoveDirectoryrrRs r7ftp_RMDz FTP.ftp_RMDsf 7 !6!6=Gzz))'2>> 5   7::/56 6 7A'A-,A-c t|j|}|j j|jdS#t$r!tjt |cYSwxYw)NctfSrgrVrs r7rzFTP.ftp_DELE..rWr6) rFrr0r rJrKrf removeFilerrRs r7ftp_DELEz FTP.ftp_DELEsf 7 !6!6=Gzz$$W-99 5   7::/56 6 7rZctfSrg)rGrps r7ftp_NOOPz FTP.ftp_NOOPs yr6c@||_|j|_tfSrg) _fromNamerr]"REQ_FILE_ACTN_PENDING_FURTHER_INFO)rkfromNames r7ftp_RNFRz FTP.ftp_RNFRs!]] 244r6cL|j}|`|j|_ t|j|}t|j|}|jj||jdS#t $r!t jt|cYSwxYw)NctfSrgrVrs r7rzFTP.ftp_RNTO..rWr6) rbrr]rFrr0r rJrKrfrenamer)rktoNamerdfromsegstosegss r7rz FTP.ftp_RNTOs>> N[[  ;!$"7"7BH 5 5v>Fzz  62>> 5   ;::/9: : ;s,A99'B#"B#c|jttd|jD]}|jd|z|jttdy)zm Advertise the features supported by the server. http://tools.ietf.org/html/rfc2389 rrrZN)rrnFEAT_OKFEATURES)rkfeatures r7ftp_FEATz FTP.ftp_FEATsS hw'*+}} )G MM#- ( ) hw'*+r6c.|jt|S)zl Handle OPTS command. http://tools.ietf.org/html/draft-ietf-ftpext-utf-8-option-00 )rVOPTS_NOT_IMPLEMENTED)rkoptions r7ftp_OPTSz FTP.ftp_OPTSs zz.77r6cp|jt|jjd|_yr)rV GOODBYE_MSGrrr}rps r7ftp_QUITz FTP.ftp_QUITs& ; %%' r6ctjddtj|j|jdc}|_tjj |r|j n:tjj |r|jn Jd||jjd|_ |jd|_ yy)z0 Call when DTP connection exits rdTrNz>dtpPort should be an IListeningPort or IConnector, instead is ) rrlrr IListeningPort providedBy stopListening IConnector disconnectrcr$r)rkrs r7rdzFTP.cleanupDTPs  D)   $ d  $ $ / / 8  ! ! #  " " - -g 6     #*- 5 ##%    '#D  (r6)r;)@r1r2r3r4r}ranger\rrrrr rfrcrrrrrnrr listenTCPrrrVrrrrirrrrrrrrrrrrrrr!r)r.r4r<r?r1rCrIrMrSrYr^r`rerrprtrwrd __classcell__)rZs@r7rKrKsH<L(-Qx$FFFHJ F EJGK Fv&O;HQ{%%MI= (-1^!?F 5$BF4L,>+ZN` F"BHT^@#GJK0*77>C >    5   ,8! $r6rKcjeZdZdZeZeZdZdZ dZ de jdZ eddZd d Zd Zd Zy ) FTPFactorya 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 anonymousiXzTwisted z FTP ServerrrZNc.||_||_g|_yrg)r r instances)rkr rs r7rizFTPFactory.__init__!s *r6ctjj||}|Q|j|j_|j |j_|j |j_|Srg)rLimitTotalConnectionsFactoryr"r wrappedProtocolr^rrs r7r"zFTPFactory.buildProtocol&s\  1 1 ? ?d K ='+{{A   $(, A   %151F1FA   .r6c|jDcgc] }|j|jd"c}tjj |ycc}wrg)rr^r/rrr$)rkr!s r7r$zFTPFactory.stopFactory.sB&*^^Mqyy7Ld M--99$? Ns AA)Nr)r1r2r3r4rKr rGoverflowProtocolrrr^rversionr`r~rrir"r$r5r6r7rr sTH*NMG 1 12+>NQ{ @r6rcJeZdZdZdZdZdZdZdZd dZ d dZ d Z d Z y ) rz An abstraction of the shell commands used by the FTP protocol for a given user account. All path names must be absolute. cy)a 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. Nr5rCs r7rQzIFTPShell.makeDirectory@rr6cy)a 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. Nr5rs r7rXzIFTPShell.removeDirectoryKrr6cy)a  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. Nr5rs r7r]zIFTPShell.removeFileVrr6cy)ax 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)fromPathtoPaths r7rhzIFTPShell.renamearr6cy)a 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. Nr5rs r7rzIFTPShell.accessorr6cy)z Retrieve information about the given path. This is like list, except it will never return results about child paths. Nr5rCkeyss r7r'zIFTPShell.statzrr6cy)ae 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 Nr5rs r7rzIFTPShell.listrr6cy)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} Nr5rs r7rzIFTPShell.openForReadingrr6cy)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} Nr5rs r7r zIFTPShell.openForWritingrr6Nr5) r1r2r3r4rQrXr]rhrr'rrr r5r6r7rr8s5           # J  r6rceZdZdZdZy) IReadFilez0 A file out of which bytes may be read. cy)a 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 r7r zIReadFile.sendrr6N)r1r2r3r4r r5r6r7rrs   r6rceZdZdZdZdZy) IWriteFilez1 A file into which bytes may be written. cy)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} Nr5r5r6r7rzIWriteFile.receiverr6cy)ae 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. Nr5r5r6r7rDzIWriteFile.closerr6N)r1r2r3r4rrDr5r6r7rrs   r6rcg}tj|}|j|jt j D]6}|j |jvs|j|j8|S)z_ Return the primary and supplementary groups for the given UID. @type uid: C{int} ) pwdgetpwuidrApw_gidgrpgetgrallpw_namegr_memgr_gid)uidrzpwentgrents r7 _getgroupsrsc F LL E MM%,,( ==ELL ( MM%,, '( Mr6c|dk(rAtj}tj}tj}tj }nU|dk(rAtj }tj}tj}tj}ntd|dd}tjj|rn|dk(rd}nft j|} || jzr|| jk(rd}n0|| jzr|t|vrd}n|| jzrd}|rDt j ||s.d}t#j$d|t j&fz|S) 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 rwz Invalid mode z: must specify 'r' or 'w'FrTzUFilesystem grants permission to UID %d but it is inaccessible to me running as UID %d)r'S_IRUSRS_IRGRPS_IROTHr9R_OKS_IWUSRS_IWGRPS_IWOTHW_OK ValueErrorrCexistsst_modest_uidrrrrlgetuid) rgidspathrLusrrothamoderrEs r7_testPermissionsrs$( s{llllll llllll=0IJKK F ww~~e !8FAQYY3!((?qyySJsO%;qyy yy&F GG7:=ryy{9KL  Mr6ceZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z dd Zdd ZdZdZdZdZdZdZdZdZy)FTPAnonymousShellz 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||_yrg)filesystemRoot)rkrs r7rizFTPAnonymousShell.__init__6s ,r6c8|jj|Srg)r descendantrkrCs r7_pathzFTPAnonymousShell._path9s""--d33r6c<tjtSrgr rJrurs r7rQzFTPAnonymousShell.makeDirectory<zz-/00r6c<tjtSrgrrs r7rXz!FTPAnonymousShell.removeDirectory?rr6c<tjtSrgrrs r7r]zFTPAnonymousShell.removeFileBrr6c<tjtSrgr)rkrrs r7rhzFTPAnonymousShell.renameErr6c^|j|}tjtSrg)rr rJrurs r7rzFTPAnonymousShell.receiveHs#zz$zz-/00r6ct|j|}|jrtjt |S |j d}tj t|S#t$r }t|j|cYd}~Sd}~wt$rtjcYSwxYw)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. rN) risdirr rJrTopenr _FileReaderOSErrorrVrHr)rkrCr!r3rUs r7rz FTPAnonymousShell.openForReadingLs JJt  779::/56 6 1s A ==Q0 0  1!!''40 0 ::<  $A00 B79BB7 B76B7c>tjtdS)za Reject write attempts by anonymous users with L{PermissionDeniedError}. zSTOR not allowed)r rJrNrs r7r z FTPAnonymousShell.openForWritinges zz/0BCDDr6c`|j|}|jstjt |S |j tj dS#t$r }t|j|cYd}~Sd}~wt$rtjcYSwxYwrg) rrr rJrKlistdirrrrVrHrrkrCr!rUs r7rzFTPAnonymousShell.accessls JJt xxz::/56 6 ' IIK ==& &  1!!''40 0 ::<  $A&& B-/B B- B-,B-cl|j|}|jr( |j||}tj|S|j||jdS#t $r }t |j|cYd}~Sd}~wt$rtjcYSwxYw)Nc|ddS)NrrZr5)ress r7rz(FTPAnonymousShell.stat..sQr6) rr _statNoder rrrVrHrrJrr)rkrCrr! statResultrUs r7r'zFTPAnonymousShell.stat|s JJt  779 1!^^At4 }}Z0099T4(445JK K 5%aggt44  $zz|# $s#A,, B35B B3 B32B3c|j|}|jr/|j}|Dcgc]}|j|}}nh|j r:t j j|j|jg}|g}ntjt|Sg}t||D]?\}}g} |j|| f|s | j|j!||Atj*|Scc}w#t"$r"} t%| j&|cYd} ~ cSd} ~ wt($rtjcYcSwxYw)a 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)rrrchildisfiler9rCr segmentsFromrr rJrKziprAextendrrrVrHrr) rkrCrfilePathentriesr! fileEntriesrfileNameentrUs r7rzFTPAnonymousShell.lists3::d# >> &&(G6=>8>>!,>K> __ ww||X%:%:4;N;N%OPQG#*K::/56 6"%g{"; ( HhC NNHc? +(JJt~~h=> (}}W%%'?=)!''8<<$( ::<'(s)D&!D## E.,E E. E.-E.c r|j|Dcgc]}t|d|z|c}Scc}w)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)rkrrks r7rzFTPAnonymousShell._statNodes5 ?CD!+hl+H5DDDs4c"|jS)z Get the filepath's size as an int @param fp: L{twisted.python.filepath.FilePath} @return: C{int} representing the size )getsizerkfps r7 _stat_sizezFTPAnonymousShell._stat_sizeszz|r6c"|jS)z Get the filepath's permissions object @param fp: L{twisted.python.filepath.FilePath} @return: L{twisted.python.filepath.Permissions} of C{fp} )getPermissionsrs r7_stat_permissionsz#FTPAnonymousShell._stat_permissionss  ""r6cB |jS#t$rYywxYw)a 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)getNumberOfHardLinksNotImplementedErrorrs r7_stat_hardlinksz!FTPAnonymousShell._stat_hardlinkss( **, ,"  s  c"|jS)z Get the filepath's last modified date @param fp: L{twisted.python.filepath.FilePath} @return: C{int} as seconds since the epoch )getModificationTimers r7_stat_modifiedz FTPAnonymousShell._stat_modifieds%%''r6c |j}t tj|dSt |S#t$r Yt |SwxYw#t $rYywxYw)a 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 r0) getUserIDrrKeyErrorrr)rkruserIDs r7 _stat_ownerzFTPAnonymousShell._stat_ownerso \\^F<</22v;  v;  #   A< AA A! A!c |j}t tj|dSt |S#t$r Yt |SwxYw#t $rYywxYw)a 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 rr) getGroupIDrgetgrgidrrr)rkrgroupIDs r7 _stat_groupzFTPAnonymousShell._stat_groupso mmoG<<033w<  w<  #  r c"|jS)z Get whether the filepath is a directory @param fp: L{twisted.python.filepath.FilePath} @return: C{bool} )rrs r7_stat_directoryz!FTPAnonymousShell._stat_directorysxxzr6Nr)r1r2r3r4rirrQrXr]rhrrr rr'rrrrrrr rrr5r6r7rr,so-41111112E' L!&F E#"(0 0r6rceZdZdZdZdZy)rc ||_d|_yr)r@_sendrAs r7riz_FileReader.__init__"s  r6cHd|_|jj|Sr)rr@rD)rk passthroughs r7_closez_FileReader._close&s  r6c|jrJdd|_tjj|j|}|j |j |S)Nz0Can only call IReadFile.send *once* per instanceT)rr FileSenderbeginFileTransferr@rr)rkrrs r7r z_FileReader.send+sO::QQQ~     0 0H E $++r6N)r1r2r3rirr r5r6r7rr s r6rc.eZdZdZdZdZdZdZdZy)FTPShellz: An authenticated implementation of L{IFTPShell}. c|j|} |jtjdS#t$r }t |j |cYd}~Sd}~wt$rtjcYSwxYwrg) rmakedirsr rrrVrHrrJrs r7rQzFTPShell.makeDirectory8sf JJt  ' JJL ==& &  1!!''40 0 ::<  s!8 A?AA? A?>A?c~|j|}|jrtjt |S t j |jtjdS#t$r }t|j|cYd}~Sd}~wt$rtjcYSwxYwrg) rrr rJrPr9rmdirrCrrrVrHrrs r7rXzFTPShell.removeDirectoryCs JJt  88:::2489 9 ' HHQVV  ==& &  1!!''40 0 ::<  s$A55 B<>BB< B<;B<c`|j|}|jrtjt |S |j tj dS#t$r }t|j|cYd}~Sd}~wt$rtjcYSwxYwrg) rrr rJrTremoverrrVrHrrs r7r]zFTPShell.removeFileSs JJt  779::/56 6 ' HHJ ==& &  1!!''40 0 ::<  rcZ|j|}|j|} tj|j|jt j dS#t $r }t|j|cYd}~Sd}~wt$rt jcYSwxYwrg) rr9rhrCr rrrVrHrrJ)rkrrrtprUs r7rhzFTPShell.renamecs ZZ ! ZZ  ' IIbggrww ' ==& &  5!!''84 4 ::<  s#*A## B*,BB* B*)B*ct|j|}|jrtjt |S |j d}tjt|S#t $r }t|j|cYd}~Sd}~wt$rtjcYSwxYw)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. rN) rrr rJrTrrrVrHrr _FileWriter)rkrCr!r@rUs r7r zFTPShell.openForWritingos JJt  779::/56 6 66#;D }}[.//  1!!''40 0 ::<  rN) r1r2r3r4rQrXr]rhr r5r6r7rr3s  '' ' '0r6rceZdZdZdZdZy)r&c ||_d|_yr)r@_receiverAs r7riz_FileWriter.__init__s  r6c|jrJdd|_tjt|jS)Nz4Can only call IWriteFile.receive *once* per instanceT)r)r rr>r@rps r7rz_FileWriter.receives4==X"XX  }}\$))455r6c,tjdSrg)r rrps r7rDz_FileWriter.closes}}T""r6N)r1r2r3rirrDr5r6r7r&r&s6 #r6r&c"eZdZdZdZdZdZy) BaseFTPRealmz{ Base class for simple FTP realms which provides an easy hook for specifying the home directory for each user. c8tj||_yrg)rFilePath anonymousRoot)rkr0s r7rizBaseFTPRealm.__init__s%..}=r6c2t|jd)a 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)rrZrkavatarIds r7getHomeDirectoryzBaseFTPRealm.getHomeDirectorys!"~~ B C  r6c|D]c}|tus |tjurt|j}nt |j |}t|t|ddfcStd)Nrbcyrgr5r5r6r7rz,BaseFTPRealm.requestAvatar..rr6z3Only IFTPShell interface is supported by this realm) rr ANONYMOUSrr0rr4rr)rkr3mindr ifacers r7 requestAvatarzBaseFTPRealm.requestAvatarsr TE !x111.t/A/ABF%d&;&;H&EFF!6768\+RSS  T""WXXr6N)r1r2r3r4rir4r:r5r6r7r-r-s >  Yr6r-ceZdZdZddZdZy)FTPRealma" @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. cdtj||tj||_yrg)r-rirr/userHome)rkr0r>s r7rizFTPRealm.__init__s$dM2 ))(3 r6c8|jj|S)z Use C{avatarId} as a single path segment to construct a child of C{self.userHome} and return that child. )r>rr2s r7r4zFTPRealm.getHomeDirectorys }}""8,,r6N)z/home)r1r2r3r4rir4r5r6r7r<r<s4-r6r<ceZdZdZdZy)SystemFTPRealmz 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. ctjjd|z}|jdrt j t j|S)zx Return the system-defined home directory of the system user account with the name C{avatarId}. ~)r9rC expanduserr>rrrr/)rkr3rCs r7r4zSystemFTPRealm.getHomeDirectorysH ww!!#.1 ??3 ..0 0  &&r6N)r1r2r3r4r4r5r6r7rArAs 'r6rAc eZdZy)ConnectionLostNrr5r6r7rFrFrr6rFc eZdZy) CommandFailedNrr5r6r7rHrHrr6rHc eZdZy) BadResponseNrr5r6r7rJrJrr6rJc eZdZy)UnexpectedResponseNrr5r6r7rLrL rr6rLc eZdZy)UnexpectedDataNrr5r6r7rNrN rr6rNceZdZddZdZy) FTPCommandNcn||_tj|_d|_||_d|_y)NrZ)textr rrreadypublictransferDeferred)rkrRrTs r7rizFTPCommand.__init__ s- (   $r6cT|jr|jj|yyrg)rTrr)rkrs r7rJzFTPCommand.fail s ;; MM ! !' * r6Nr)r1r2r3rirJr5r6r7rPrP s %+r6rPc$eZdZdZdZdZdZy)ProtocolWrapperc ||_||_yrg)originalr)rkr[rs r7rizProtocolWrapper.__init__ s    r6c:|jj|yrg)r[makeConnectionrkrs r7r]zProtocolWrapper.makeConnection s $$Y/r6c:|jj|yrg)r[rrs r7rzProtocolWrapper.dataReceived s ""4(r6cp|jj||jjdyrg)r[rrrrs r7rzProtocolWrapper.connectionLost" s& $$V, t$r6N)r1r2r3rir]rrr5r6r7rYrY s!0)%r6rYceZdZdZdZy)IFinishableConsumerzA A Consumer for producers that finish. @since: 11.0 cy)z6 The producer has finished producing. Nr5r5r6r7finishzIFinishableConsumer.finish/ rr6N)r1r2r3r4rdr5r6r7rbrb( s   r6rbc<eZdZdZdZdZdZdZdZdZ dZ y ) SenderProtocolchtj|_tj|_yrg)r rconnectedDeferredrrps r7rizSenderProtocol.__init__7 s!!&!1( r6ctd)Nz <  c ";;t~~.D ##D$/r6c|j}|d|_y|jsD|jj d|t j d|jd|_y|jdk(r|j||jr"tjd|jz|j|_|j|jy)zD (Private) Processes the next command in the queue. Nrg?PORTz<-- %s)popCommandQueuerrSrinsertr r-sendNextCommandrRgeneratePortCommandrrrlrrrkrs r7rzFTPClientBasic.sendNextCommand s))+   $D      # #Az 2   c4#7#7 8 $D   ??f $  $ $Z 0 :: GGHz. /&// joo&r6c|jj|t|jdk(r+|j|j|j yyyy)a 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} rZN)rrAr;rrrrs r7 queueCommandzFTPClientBasic.queueCommand s\  +   !Q &*!!)  "*+ 'r6cTt||}|j||jS)au 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. )rPrr)rkrrTrs r7queueStringCommandz!FTPClientBasic.queueStringCommand s* 0  *%"""r6cR|jr|jjdSy)zR Return the front element of the command queue, or None if empty. rN)rr@rps r7rzFTPClientBasic.popCommandQueue s'   ##''* *r6clg}jd|zd}|j||Std|zdj|jjfd}|j ||D]/}|j j|j d1y)a  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. zUSER rrTNzPASS cf|djdrjj|S)Nr230)r>rr")rq passwordCmdrks r7cancelPasswordIfNotNeededz.cancelPasswordIfNotNeeded" s.A;))%0$$++K8r6cyrgr5rys r7rz+FTPClientBasic.queueLogin../ rr6)rrArPrrrrrJ)rkrr deferreds userDeferredrrrs` @r7 queueLoginzFTPClientBasic.queueLogin s ..w/A!.L &  $Wx%7BK   k *   [11 2  $ $%> ?" 0H    *    /  0r6c*ttk7r|j|j}|jrt j d|z|jj|tjd|}|sy|dd}|ddk(ry|j%|jt|jy|j}g|_|ddvr|jj|n|ddvr8|jjt!j"t%|nOt j d ||jjt!j"t'||j)y) zM (Private) Parses the response messages from the FTP server. z--> %sz\d{3} Nr1)23)45z"Server sent invalid response code )rrrrrrrlrqrArtmatchrrJrLrrrrrHrJr)rkr codeIsValidr;rqs r7rzFTPClientBasic.lineReceived1 sH C<;;t~~.D :: GGHtO $ T"hhy$/  Aay 7c>     $ II(7 8 ==  7j    & &x 0 !W "    % %goomH6M&N O GG8? @    % %gook(6K&L M r6c&|j|yrgrrs r7rzFTPClientBasic.connectionLosta s 6r6N)rZ)r1r2r3r4rrrirJrrrrrrrrrrr5r6r7rr sQ EI *! 0'0#$ #"0H.`r6rc"eZdZdZdZdZdZy)_PassiveConnectionFactoryFc||_yrg) protoInstance)rkrs r7riz"_PassiveConnectionFactory.__init__h s *r6c<||j_|jSrg)rrrs r7r"z'_PassiveConnectionFactory.buildProtocolk s%)"!!!r6cftd|}|jjj|y)NzConnection Failed)rrrr)rkr1rrUs r7r2z0_PassiveConnectionFactory.clientConnectionFailedo s) (& 1 ##++A.r6N)r1r2r3rrir"r2r5r6r7rre s E+"/r6rceZdZdZej Z ddZdZdZ dZ dZ dZ dZ d Zdd ZeZdd ZeZd Zd ZdZdZdZdZdZdZdZdZdZy) FTPClientaI 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} for error code definitions. Both active and passive transfers are supported. @ivar passive: See description in __init__. c`tj||j||||_y)ay 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)rrirpassive)rkrrrs r7rizFTPClient.__init__ s' % (+ r6cZ|jj|j|y)zM Disconnect, and also give an error to any queued deferreds. N)rrrrs r7rJzFTPClient.fail s  %%' 5r6ctj|}t|tj}|j ||S)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 IProtocolrYr r_openDataConnection)rkcommandsr wrappers r7receiveFromConnectionzFTPClient.receiveFromConnection s:''1!(ENN,<='''::r6ctj||||jdd}|j|j|jdy)zg Login: send the username, send the password, and set retrieval mode to binary zTYPE Irrcyrgr5rs r7rz&FTPClient.queueLogin.. rr6N)rrrrrJ)rkrrrs r7rzFTPClient.queueLogin sG !!$(;  # #HQ # 7 TYY ^$r6cVt}|j||}|j|fS)aQ 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. )rfrrh)rkrrErs r7sendToConnectionzFTPClient.sendToConnection s/    $ $Xq 1##Q''r6c. |Dcgc]}t|d}}tj|Dcgc]}|jc}dd}|j t j rdg fd}td}j||jj|j j||jjg} tj| dd} | j t  fd} | j| ntd } j| _ | _ | jj | jjj| d | _d | _ |j | fd || j| jg} tj| dd} | j t |D]}j|| Scc}wcc}w) z5 This method returns a DeferredList. rZrT)fireOnOneErrback consumeErrorsNcpt|ddd\}}t}j|||d<y)z5Connect to the port specified in the response to PASVrYrLNr)r}rconnectFactory)rqrrr3_mutabler rks r7 doPassivez0FTPClient._openDataConnection..doPassive s>+HRL,<= d-h7"11$a@ r6rQc:|dxr|dj|SrW)r})ryms r7rDz,FTPClient._openDataConnection..close s!*1*r6rc|Srgr5rs r7rz/FTPClient._openDataConnection.. sFr6c|Srgr5)rs r7rz/FTPClient._openDataConnection.. sr6c,|j|xs|Srg)rJ)rUpcs r7rz/FTPClient._openDataConnection.. s"''!*/r6)rPr DeferredListrrrrrrrJrrUr rr)rkrr rcmdsru cmdsDeferredrpasvCmdrrrDportCmdrs` ` @r7rzFTPClient._openDataConnection s>FF' 71-FF))%) *cS\\ *TQU   12 <<vH A!(G   g &    ( ( 3 > >tyy I#W%5%5x7H7HIG""7TQUVA LL* +$  IIe  !(G(0'8'8G $'G     ' '(@(@(H(H I   g & &;G ".GL  # #$I J#W%5%5w7O7OPG""7TQUVA LL* + #C   c " #CG *s H Hc0t}|j|_tjd|}||_|fd}||_|j jj}|jj}dt||z|_ y)zG (Private) Generates the text of a given PORT command. rc>|jr|j|Srg)rr)rlisteners r7 listenerFailz3FTPClient.generatePortCommand..listenerFail. s!!'')Lr6zPORT N) rr r rrrJrrrrrR)rkrrrrrrs r7rzFTPClient.generatePortCommand s"%&"++$$Q0 *2  $ ~~%%',,!&&d!;; r6c&|jddS)zK Returns a FTP escaped path (replace newlines with nulls).  r=)r^rs r7 escapePathzFTPClient.escapePath: s ||D$''r6cd|j|zg}|r|jddt|z|j||S)a 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} zRETR rREST )rrrr)rkrCr offsetrs r7 retrieveFilezFTPClient.retrieveFileA sG$//$//0  KKGc&k1 3))$99r6cd|j|zg}|r|jddt|z|j|S)a 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. zSTOR rr)rrrr)rkrCrrs r7 storeFilezFTPClient.storeFileW sE$//$//0  KKGc&k1 3$$T**r6cRjdj|z}jdj|z}gtjj fdfd}|j j ||jS)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 zRNFR zRNTO c |fSrgr5) toResponse fromResponses r7rz"FTPClient.rename.. s |Z.Hr6cHjj|yrg)rr)rrzrks r7ebFromz FTPClient.rename..ebFrom s  " NN7 #r6)rrr rrrr chainDeferred)rkpathFrompathTo renameFromrenameTorrrzs` @@r7rhzFTPClient.renamej s0,,Wtx7P-PQ **7T__V5L+LM !HI $  3 3V< v& r6cT|d}|jd|j|zg|S)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} r;zLIST rrrkrCr s r7rzFTPClient.list s2 <D))7T__T5J+J*KXVVr6cT|d}|jd|j|zg|S)a1 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. r;zNLST rrs r7nlstzFTPClient.nlst s2 <D))7T__T5J+J*KXVVr6cH|jd|j|zS)z Issues the CWD (Change Working Directory) command. @return: a L{Deferred} that will be called when done. zCWD rrrs r7rBz FTPClient.cwd s# &&v0E'EFFr6cH|jd|j|zS)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 zMKD rrs r7rQzFTPClient.makeDirectory #$&&v0E'EFFr6cH|jd|j|zS)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 zDELE rrs r7r]zFTPClient.removeFile s#$&&w1F'FGGr6cH|jd|j|zS)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 zRMD rrs r7rXzFTPClient.removeDirectory rr6c$|jdS)z Issues the CDUP (Change Directory UP) command. @return: a L{Deferred} that will be called when done. CDUPrrps r7cdupzFTPClient.cdup s &&v..r6c$|jdS)ah 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 rps r7rz FTPClient.pwd s&&u--r6cFd}|jj|S)a 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  t|djddddk7rt t|d}|t j t |S|S#ttf$r!t j t |cYSwxYw)NrrrZi)rr?r IndexErrorrrrHparsePWDResponse)rzrCs r7cbParsez'FTPClient.getDirectory..cbParse s >vaysA.q12c9$$:$F1I.D|}V'<==K  + >}V'<== >s*A-B  B )rr)rkrs r7 getDirectoryzFTPClient.getDirectory s  xxz%%g..r6c$|jdS)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. rOr rps r7quitzFTPClient.quit* s&&v..r6N)rztwisted@twistedmatrix.comrZ)r)r1r2r3r4r rrrirJrrrrrrrretrrstorrhrrrBrQr]rXr rrrr5r6r7rrt s(''NST&;" % (EN! 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.)(?P.{9})\s+(?P\d*)\s*(?P\S+)\s+(?P\S+)\s+(?P\d+)\s+(?P...\s+\d+\s+[\d:]+)\s+(?P.{1,}?)( -> (?P[^\r]*))?\r?$ rcg|_yrg)filesrps r7rizFTPFileListProtocol.__init__h s  r6cttk7r|j|j}|j |}||j |y|j |yrg)rrrrparseDirectoryLine unknownLineaddFile)rkrrs r7rz FTPFileListProtocol.lineReceivedk sI C<;;t~~.D  # #D ) 9   T " LLOr6c|jj|}|y|j}|djdd|d<t |d|d<t |d|d<|dr|djdd|d<|S)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 Nfilenamez\ rnlinksr linktarget)fileLinePatternr groupdictr^r)rkrrrs r7rz&FTPFileListProtocol.parseDirectoryLinet s$$**40 =!AjM11%=AjMak*AhKAfIAfI"#L/"9"9%"E,Hr6c:|jj|y)a 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)rrA)rkrs r7rzFTPFileListProtocol.addFile s $r6cy)a 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 Nr5rs r7rzFTPFileListProtocol.unknownLine s r6N)r1r2r3r4rtcompiler$ delimiterrrirrrrr5r6r7rr5 sD'R!bjj -O II*    r6rcZtjd|}|r|jdSy)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"(.*)"rN)rtsearchgroups)rqrs r7rr s+ IIh )E ||~a  r6rg)r)r4rHr[r9rtr'rrr ImportErrorzope.interfacerrtwistedr twisted.credrrrrr rr r r r twisted.protocolsrrtwisted.pythonrrrRESTART_MARKER_REPLYSERVICE_READY_IN_N_MINUTESrr rGr9rCMD_NOT_IMPLMNTD_SUPERFLUOUSSYS_STATUS_OR_HELP_REPLYrm DIR_STATUSr$HELP_MSGrBSVC_READY_FOR_NEW_USERr_SVC_CLOSING_CTRL_CNXrv DATA_CNX_OPEN_NO_XFR_IN_PROGRESSCLOSING_DATA_CNXrrENTERING_EPSV_MODErrrrrPrrNEED_ACCT_FOR_LOGINrcSVC_NOT_AVAIL_CLOSING_CTRL_CNXrIrrREQ_ACTN_ABRTD_FILE_UNAVAILREQ_ACTN_ABRTD_LOCAL_ERRREQ_ACTN_ABRTD_INSUFF_STORAGErrrrrrrrrNEED_ACCT_FOR_STORrsrxrvrzrtr}r PAGE_TYPE_UNKEXCEEDED_STORAGE_ALLOCFILENAME_NOT_ALLOWEDrnrhr0rFrVr\r]rcrerKrurNrPrRrTrrrrrrrrrr IConsumerrkr ClientFactoryrr6r>rrG TimeoutMixinrKrrrrrrrrrrr&IRealmr-r<rArFrHrJrLrNrPrYrbrfr}rr ServerFactoryrrrrrrr5r6r7rLs   2KKHH-11 ""'$  $"        #( !"   "%*"!(#  %   "     N .N  A N  $& N !#N  N &N  N !#N 7N   oy )!N "#N $%N & n'N (&)N *+N ,/-N .E/N 01N 2%'3N 6,7N 8.9N :9;N >I?N @8AN BTCN F KGN HzIN J!KN N:ON PQN T6UN V')WN \#%]N `aN d9eN fPgN h !UiN j!kN n"$oN t&uN v=wN x8yN z<{N |<}N ~ LN @9AN B5CN DBEN F8GN H3IN JUKN L<& &<*'T[N b) 2$%7$$V,B <) <  !+!"K";k [# #![!+;+ y  ) +8 " Z ! !"K'(  K'#K'\]/'']/FBB" Z ! !"#.(%,,(F $%  h33F $R&@66&@X} } @  "  2$5p Ypppf Y$R0 R0j Z # # # V]]YYYD-|-,'\'J X  H  (    X  + +%h''%"  *..   !)(X&&)(")(X" $ //&RU''Rj / 6 6 /~/~/Bm %,,m `adC#sR(( R54R5