grthtrhthjhtyjytjytkergtrhtrjytjerhrfh4:24 29/09/2026o ®û|j¡Œã@sNdZddlZddlZddlmZgd¢ZdZdZdZGdd „d eƒZ Gd d „d e ƒZ Gd d „d e ƒZ Gdd„de ƒZ Gdd„de ƒZ e eefZdZdZGdd„dƒZzddlZWn eycdZYnwejZGdd„deƒZe d¡e eeejfZdadd„Zdadd„Zdd„Zdd„Z d d!„Z!d)d$d%„Z"d&d'„Z#e$d(kr¥e#ƒdSdS)*aSAn FTP client class and some helper functions. Based on RFC 959: File Transfer Protocol (FTP), by J. Postel and J. Reynolds Example: >>> from ftplib import FTP >>> ftp = FTP('ftp.python.org') # connect to host, default port >>> ftp.login() # default, i.e.: user anonymous, passwd anonymous@ '230 Guest login ok, access restrictions apply.' >>> ftp.retrlines('LIST') # list directory contents total 9 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 . drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .. drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg '226 Transfer complete.' >>> ftp.quit() '221 Goodbye.' >>> A nice test that reveals some of the network dialogue would be: python ftplib.py -d localhost -l -p -l éN)Ú_GLOBAL_DEFAULT_TIMEOUT)ÚFTPÚ error_replyÚ error_tempÚ error_permÚ error_protoÚ all_errorsééé c@ó eZdZdS)ÚErrorN©Ú__name__Ú __module__Ú __qualname__©rrú-/opt/alt/python310/lib64/python3.10/ftplib.pyr 9ó r c@r )rNrrrrrr:rrc@r )rNrrrrrr;rrc@r )rNrrrrrr<rrc@r )rNrrrrrr=rrú s c@sªeZdZdZdZdZeZeZ dZ dZ dZ dZ dZddddedfddœd d „Zd d „Zd d„Zd]dd„Zdd„Zdd„ZeZdd„Zdd„Zdd„Zdd„Zdd„Zd d!„Zd"d#„Zd$d%„Zd&d'„Zd(d)„Z d*d+„Z!d,d-„Z"d.d/„Z#d0d1„Z$d2d3„Z%d^d4d5„Z&d^d6d7„Z'd_d8d9„Z(d`d;d<„Z)d^d=d>„Z*dad?d@„Z+d^dAdB„Z,dCdD„Z-dEdF„Z.dGdH„Z/dgfdIdJ„Z0dKdL„Z1dMdN„Z2dOdP„Z3dQdR„Z4dSdT„Z5dUdV„Z6dWdX„Z7dYdZ„Z8d[d\„Z9dS)bruôAn FTP client class. To create a connection, call the class using these arguments: host, user, passwd, acct, timeout, source_address, encoding The first four arguments are all strings, and have default value ''. The parameter ´timeout´ must be numeric and defaults to None if not passed, meaning that no timeout will be set on any ftp socket(s). If a timeout is passed, then this is now the default timeout for all ftp socket operations for this instance. The last parameter is the encoding of filenames, which defaults to utf-8. Then use self.connect() with optional host and port argument. To download a file, use ftp.retrlines('RETR ' + filename), or ftp.retrbinary() with slightly different arguments. To upload a file, use ftp.storlines() or ftp.storbinary(), which have an open file as argument (see their definitions below for details). The download/upload functions first issue appropriate TYPE and PORT or PASV commands. rÚNTFúutf-8©ÚencodingcCs>||_||_||_|r| |¡|r| |||¡dSdSdS)zãInitialization method (called by class instantiation). Initialize host to localhost, port to standard ftp port. Optional arguments are host (for connect()), and user, passwd, acct (for login()). N)rÚsource_addressÚtimeoutÚconnectÚlogin)ÚselfÚhostÚuserÚpasswdÚacctrrrrrrÚ__init__ms ýz FTP.__init__cCs|S©Nr©rrrrÚ __enter__}sz FTP.__enter__c Gsf|jdur1z z| ¡Wn ttfyYnwW|jdur$| ¡dSdS|jdur0| ¡wwdSr$)ÚsockÚquitÚOSErrorÚEOFErrorÚclose)rÚargsrrrÚ__exit__�s  ÿ€  ÿ ÿúz FTP.__exit__éüÿÿcCs°|dkr||_|dkr||_|dkr||_|jdur!|js!tdƒ‚|dur(||_t d||j|j¡tj|j|jf|j|jd�|_ |j j |_ |j j d|j d �|_| ¡|_|jS) awConnect to host. Arguments are: - host: hostname to connect to (string, default previous host) - port: port to connect to (integer, default previous port) - timeout: the timeout to set against the ftp socket(s) - source_address: a 2-tuple (host, port) for the socket to bind to as its source address before connecting. rrr.Nz0Non-blocking socket (timeout=0) is not supportedzftplib.connect©rÚrr)rÚportrÚ ValueErrorrÚsysÚauditÚsocketÚcreate_connectionr'ÚfamilyÚafÚmakefilerÚfileÚgetrespÚwelcome)rrr1rrrrrr‹s$ÿ  z FTP.connectcCs|jr td| |j¡ƒ|jS)z`Get the welcome message from the server. (this is read and squirreled away by connect())z *welcome*)Ú debuggingÚprintÚsanitizer<r%rrrÚ getwelcome¥szFTP.getwelcomecCó ||_dS)zðSet the debugging level. The required argument level means: 0: no debugging output (default) 1: print commands and responses but not body text etc. 2: also print raw lines read and sent before stripping CR/LFN)r=)rÚlevelrrrÚset_debuglevel¬s zFTP.set_debuglevelcCrA)z›Use passive or active mode for data transfers. With a false argument, use the normal PORT mode, With a true argument, use the PASV command.N)Ú passiveserver)rÚvalrrrÚset_pasvµs z FTP.set_pasvcCsJ|dd…dvr!t| d¡ƒ}|dd…d|d||d…}t|ƒS)Né>úPASS zpass rÚ*)ÚlenÚrstripÚrepr)rÚsÚirrrr?¼s$z FTP.sanitizecCs`d|vsd|vr tdƒ‚t d||¡|t}|jdkr$td| |¡ƒ|j |  |j ¡¡dS)Nú Ú z4an illegal newline character should not be containedzftplib.sendcmdr z*put*) r2r3r4ÚCRLFr=r>r?r'ÚsendallÚencoder©rÚlinerrrÚputlineÃs z FTP.putlinecCs$|jr td| |¡ƒ| |¡dS)Nz*cmd*)r=r>r?rVrTrrrÚputcmdÍsz FTP.putcmdcCs�|j |jd¡}t|ƒ|jkrtd|jƒ‚|jdkr$td| |¡ƒ|s(t‚|dd…t kr8|dd…}|S|dd…t vrF|dd…}|S)Nr úgot more than %d bytesz*get*éþÿÿÿéÿÿÿÿ) r:ÚreadlineÚmaxlinerJr r=r>r?r*rQrTrrrÚgetlineÓs  þ z FTP.getlinecCsf| ¡}|dd…dkr1|dd…} | ¡}|d|}|dd…|kr0|dd…dkr0 |Sq|S)Nééú-r rP)r])rrUÚcodeZnextlinerrrÚ getmultilineås  úzFTP.getmultilinecCsl| ¡}|jrtd| |¡ƒ|dd…|_|dd…}|dvr"|S|dkr*t|ƒ‚|dkr2t|ƒ‚t|ƒ‚)Nz*resp*r^r >Ú3Ú2Ú1Ú4Ú5)rbr=r>r?Zlastresprrr)rÚrespÚcrrrr;ós z FTP.getrespcCs$| ¡}|dd…dkrt|ƒ‚|S)z%Expect a response beginning with '2'.Nr rd)r;r©rrhrrrÚvoidrespsz FTP.voidrespcCsTdt}|jdkrtd| |¡ƒ|j |t¡| ¡}|dd…dvr(t|ƒ‚|S)züAbort a file transfer. Uses out-of-band data. This does not follow the procedure from the RFC to send Telnet IP and Synch; that doesn't seem to work with the servers I've tried. Instead, just send the ABOR command as OOB data.óABORr z *put urgent*Nr^¾Z225Z426Z226) ÚB_CRLFr=r>r?r'rRÚMSG_OOBrbr©rrUrhrrrÚaborts z FTP.abortcCó| |¡| ¡S)z'Send a command and return the response.)rWr;©rÚcmdrrrÚsendcmdó z FTP.sendcmdcCrr)z8Send a command and expect a response beginning with '2'.)rWrkrsrrrÚvoidcmdrvz FTP.voidcmdcCsB| d¡}t|dƒt|dƒg}||}dd |¡}| |¡S)zUSend a PORT command with the current host and the given port number. Ú.ézPORT ú,)ÚsplitrLÚjoinrw)rrr1ZhbytesZpbytesÚbytesrtrrrÚsendport s  z FTP.sendportcCsbd}|jtjkr d}|jtjkrd}|dkrtdƒ‚dt|ƒ|t|ƒdg}dd |¡}| |¡S)zESend an EPRT command with the current host and the given port number.rr ézunsupported address familyrzEPRT ú|)r8r5ÚAF_INETZAF_INET6rrLr|rw)rrr1r8ZfieldsrtrrrÚsendeprt*s   z FTP.sendeprtcCsltjd|jdd�}| ¡d}|j ¡d}|jtjkr#| ||¡}n| ||¡}|jt ur4|  |j¡|S)z3Create a new socket and send a PORT command for it.)rrr )r7Zbacklogr) r5Z create_serverr8Z getsocknamer'r�r~r‚rrÚ settimeout)rr'r1rrhrrrÚmakeport7s     z FTP.makeportcCsh|jtjkr#t| d¡ƒ\}}|jr|}||fS|j ¡d}||fSt| d¡|j ¡ƒ\}}||fS)z (address, port)ÚPASVrZEPSV) r8r5r�Úparse227ruÚtrust_server_pasv_ipv4_addressr'Ú getpeernameÚparse229)rÚuntrusted_hostr1rrrrÚmakepasvDs ýÿz FTP.makepasvc Cs>d}|jrF| ¡\}}tj||f|j|jd�}z&|dur#| d|¡| |¡}|ddkr2| ¡}|ddkrrr`z anonymous@zUSER rrcrHúACCT rd©rur)rr r!r"rhrrrr‹s    z FTP.loginr cCs¢| d¡| ||¡�:} | |¡}|sn||ƒq tdur1t|tƒr;| ¡Wdƒ| ¡SWdƒ| ¡SWdƒ| ¡S1sHwY| ¡S)aÆRetrieve data in binary mode. A new port is created for you. Args: cmd: A RETR command. callback: A single parameter callable to be called on each block of data read. blocksize: The maximum number of bytes to read from the socket at one time. [default: 8192] rest: Passed to transfercmd(). [default: None] Returns: The response code. úTYPE Ir N)rwr’ZrecvÚ _SSLSocketÚ isinstanceÚunwraprk)rrtÚcallbackÚ blocksizerŽr�ÚdatarrrÚ retrbinary¥s(  ü  ø þ ù þ ù ÷ zFTP.retrbinaryc Cs<|durt}| d¡}| |¡�‚}|jd|jd��]} | |jd¡}t|ƒ|jkr1td|jƒ‚|j dkr=t dt |ƒƒ|s@n"|d d…t krO|dd …}n|d d…d kr]|dd …}||ƒqt durot|t ƒro| ¡Wdƒn1sywYWdƒ| ¡SWdƒ| ¡S1s•wY| ¡S) ahRetrieve data in line mode. A new port is created for you. Args: cmd: A RETR, LIST, or NLST command. callback: An optional single parameter callable that is called for each line with the trailing CRLF stripped. [default: print_line()] Returns: The response code. NúTYPE Ar0rr rXrz*retr*rYrZrP)Ú print_linerur’r9rr[r\rJr r=r>rLrQr–r—r˜rk)rrtr™rhr�ÚfprUrrrÚ retrlines¿s<   ÿ  ô€(ï îîz FTP.retrlinescCs°| d¡| ||¡�A} | |¡}|sn | |¡|r ||ƒq tdur8t|tƒrB| ¡Wdƒ| ¡SWdƒ| ¡SWdƒ| ¡S1sOwY| ¡S)a9Store a file in binary mode. A new port is created for you. Args: cmd: A STOR command. fp: A file-like object with a read(num_bytes) method. blocksize: The maximum data size to read from fp and send over the connection at once. [default: 8192] callback: An optional single parameter callable that is called on each block of data after it is sent. [default: None] rest: Passed to transfercmd(). [default: None] Returns: The response code. r•r N)rwr’ÚreadrRr–r—r˜rk)rrtrŸršr™rŽr�ÚbufrrrÚ storbinaryâs,   ú  ö þ ÷ þ ÷ õ zFTP.storbinarycCs| d¡| |¡�j} | |jd¡}t|ƒ|jkr"td|jƒ‚|s%n$|dd…tkr=|dtvr9|dd…}|t}| |¡|rH||ƒq tdur`t |tƒrj|  ¡Wdƒ|  ¡SWdƒ|  ¡SWdƒ|  ¡S1swwY|  ¡S)ahStore a file in line mode. A new port is created for you. Args: cmd: A STOR command. fp: A file-like object with a readline() method. callback: An optional single parameter callable that is called on each line after it is sent. [default: None] Returns: The response code. r�r rXrYNrZ) rwr’r[r\rJr rnrRr–r—r˜rk)rrtrŸr™r�r¢rrrÚ storlinesÿs6  õ  ñþ òþ òðz FTP.storlinescCsd|}| |¡S)zSend new account name.r“©rw)rZpasswordrtrrrr"s zFTP.acctcGs0d}|D]}|d|}qg}| ||j¡|S)zBReturn a list of files in a given directory (default the current).ZNLSTú )r Úappend)rr,rtÚargÚfilesrrrÚnlst#s zFTP.nlstcGshd}d}|dd…rt|dƒtdƒkr|dd…|d}}|D] }|r+|d|}q!| ||¡dS)aList a directory in long form. By default list current directory to stdout. Optional last argument is callback function; all non-empty arguments before it are concatenated to the LIST command. (This *should* only be used for a pathname.)ZLISTNrZrr¦)Útyper )rr,rtÚfuncr¨rrrÚdir,s  €zFTP.dirc cs¨�|r| dd |¡d¡|rd|}nd}g}| ||j¡|D].}| t¡ d¡\}}}i} |dd… d¡D]} |  d¡\} }} | | |  ¡<q;|| fVq#dS) a<List a directory in a standardized format by using MLSD command (RFC-3659). If path is omitted the current directory is assumed. "facts" is a list of strings representing the type of information desired (e.g. ["type", "size", "perm"]). Return a generator object yielding a tuple of two elements for every file found in path. First element is the file name, the second one is a dictionary including a variable number of "facts" depending on the server and whether "facts" argument has been provided. z OPTS MLST ú;zMLSD %sZMLSDr¦NrZú=) rur|r r§rKrQÚ partitionr{Úlower) rÚpathZfactsrtÚlinesrUZ facts_foundÚ_ÚnameÚentryZfactÚkeyÚvaluerrrÚmlsd;s €   úzFTP.mlsdcCs0| d|¡}|ddkrt|ƒ‚| d|¡S)zRename a file.zRNFR rrczRNTO )rurrw)rZfromnameZtonamerhrrrÚrenameWs z FTP.renamecCs*| d|¡}|dd…dvr|St|ƒ‚)zDelete a file.zDELE Nr^>Z250Z200r”)rÚfilenamerhrrrÚdelete^sz FTP.deletec Csp|dkr)z| d¡WSty(}z|jddd…dkr‚WYd}~n d}~ww|dkr/d}d |}| |¡S) zChange to a directory.z..ZCDUPrNr^Ú500rrxzCWD )rwrr,)rÚdirnameÚmsgrtrrrÚcwdfs  ÿ€ÿ zFTP.cwdcCs:| d|¡}|dd…dkr|dd… ¡}t|ƒSdS)zRetrieve the size of a file.zSIZE Nr^Z213)ruÚstripÚint)rr»rhrMrrrr�ss þzFTP.sizecCs$| d|¡}| d¡sdSt|ƒS)z+Make a directory, return its full pathname.zMKD Ú257r©rwÚ startswithÚparse257)rr¾rhrrrÚmkd{s zFTP.mkdcCs| d|¡S)zRemove a directory.zRMD r¥)rr¾rrrÚrmd„szFTP.rmdcCs | d¡}| d¡s dSt|ƒS)z!Return current working directory.ZPWDrÃrrÄrjrrrÚpwdˆs  zFTP.pwdcCs| d¡}| ¡|S)zQuit, and close the connection.ZQUIT)rwr+rjrrrr(‘s zFTP.quitcCsdz!|j}d|_|dur| ¡W|j}d|_|dur | ¡dSdS|j}d|_|dur1| ¡ww)z8Close the connection without assuming anything about it.N)r:r+r')rr:r'rrrr+—s € ÿþ ÿz FTP.close)rrr.Nr$)rrr)r N)r NN):rrrÚ__doc__r=rÚFTP_PORTr1ÚMAXLINEr\r'r:r<rDr‡rr#r&r-rr@rCÚdebugrFr?rVrWr]rbr;rkrqrurwr~r‚r„r‹r‘r’rrœr r£r¤r"rªr­r¹rºr¼rÀr�rÇrÈrÉr(r+rrrrrJsrÿ þ     7    #     rc s„eZdZdZejZdddddddedf ddœ‡fdd„ Zd‡fd d „ Z d d „Z d d„Z dd„Z dd„Z d‡fdd„ Zdd„Z‡ZS)ÚFTP_TLSa¯A FTP subclass which adds TLS support to FTP as described in RFC-4217. Connect as usual to port 21 implicitly securing the FTP control connection before authenticating. Securing the data connection requires user to explicitly ask for it by calling prot_p() method. Usage example: >>> from ftplib import FTP_TLS >>> ftps = FTP_TLS('ftp.python.org') >>> ftps.login() # login anonymously previously securing control channel '230 Guest login ok, access restrictions apply.' >>> ftps.prot_p() # switch to secure data connection '200 Protection level set to P' >>> ftps.retrlines('LIST') # list directory content securely total 9 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 . drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .. drwxr-xr-x 2 root wheel 1024 Jan 3 1994 bin drwxr-xr-x 2 root wheel 1024 Jan 3 1994 etc d-wxrwxr-x 2 ftp wheel 1024 Sep 5 13:43 incoming drwxr-xr-x 2 root wheel 1024 Nov 17 1993 lib drwxr-xr-x 6 1094 wheel 1024 Sep 13 19:07 pub drwxr-xr-x 3 root wheel 1024 Jan 3 1994 usr -rw-r--r-- 1 root root 312 Aug 1 1994 welcome.msg '226 Transfer complete.' >>> ftps.quit() '221 Goodbye.' >>> rNrrc  s¦|dur |dur tdƒ‚|dur|durtdƒ‚|dus |dur+ddl} |  dtd¡||_||_|dur>tj|j||d�}||_ d|_ t ƒj |||||| | d�dS) Nz4context and keyfile arguments are mutually exclusivez5context and certfile arguments are mutually exclusiverzAkeyfile and certfile are deprecated, use a custom context insteadr)ÚcertfileÚkeyfileFr) r2ÚwarningsÚwarnÚDeprecationWarningrÐrÏÚsslZ_create_stdlib_contextÚ ssl_versionÚcontextÚ_prot_pÚsuperr#) rrr r!r"rÐrÏrÖrrrrÑ©Ú __class__rrr#Îs*ÿþ ÿzFTP_TLS.__init__Tcs*|r t|jtjƒs | ¡tƒ |||¡Sr$)r—r'rÔÚ SSLSocketÚauthrØr)rr r!r"ZsecurerÙrrrçsz FTP_TLS.logincCsft|jtjƒr tdƒ‚|jtjkr| d¡}n| d¡}|jj |j|j d�|_|jj d|j d�|_ |S)z2Set up secure control connection by using TLS/SSL.zAlready using TLSzAUTH TLSzAUTH SSL©Zserver_hostnamer0)Úmoder)r—r'rÔrÛr2rÕZ PROTOCOL_TLSrwrÖÚ wrap_socketrr9rr:rjrrrrÜìs   z FTP_TLS.authcCs0t|jtjƒs tdƒ‚| d¡}|j ¡|_|S)z/Switch back to a clear-text control connection.z not using TLSZCCC)r—r'rÔrÛr2rwr˜rjrrrÚcccøs   z FTP_TLS.ccccCs| d¡| d¡}d|_|S)zSet up secure data connection.zPBSZ 0zPROT PT©rwr×rjrrrÚprot_ps zFTP_TLS.prot_pcCs| d¡}d|_|S)z"Set up clear text data connection.zPROT CFrárjrrrÚprot_cs zFTP_TLS.prot_ccs2tƒ ||¡\}}|jr|jj||jd�}||fS)NrÝ)rØr‘r×rÖrßr)rrtrŽr�r�rÙrrr‘s ÿzFTP_TLS.ntransfercmdcCs8dt}|j |¡| ¡}|dd…dvrt|ƒ‚|S)Nrlr^rm)rnr'rRrbrrprrrrqs  z FTP_TLS.abort)rrrTr$)rrrrÊrÔZPROTOCOL_TLS_CLIENTrÕrr#rrÜràrârãr‘rqÚ __classcell__rrrÙrrΫs  þý rÎcCs\|dd…dkr t|ƒ‚tdurddl}| d|j|jB¡at |¡}|s'dSt| d¡ƒS)zžParse the '150' response for a RETR request. Returns the expected transfer size or None; size is not guaranteed to be present in the 150 message. Nr^rŒrz150 .* \((\d+) bytes\)r ) rÚ_150_reÚreÚcompileÚ IGNORECASEÚASCIIÚmatchrÂÚgroup)rhræÚmrrrr�.s ÿ r�cCsŠ|dd…dkr t|ƒ‚tdurddl}| d|j¡at |¡}|s&t|ƒ‚| ¡}d |dd…¡}t |dƒd>t |d ƒ}||fS) z¢Parse the '227' response for a PASV request. Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)' Return ('host.addr.as.numbers', port#) tuple.Nr^Z227rz#(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)rxr_érG) rÚ_227_rerærçréÚsearchrÚgroupsr|rÂ)rhrærìZnumbersrr1rrrr†Bs r†cCsÀ|dd…dkr t|ƒ‚| d¡}|dkrt|ƒ‚| d|d¡}|dkr)t|ƒ‚||d||dkr9t|ƒ‚||d|… ||d¡}t|ƒdkrRt|ƒ‚|d}t|dƒ}||fS) zšParse the '229' response for an EPSV request. Raises error_proto if it does not contain '(|||port|)' Return ('host.addr.as.numbers', port#) tuple.Nr^Z229ú(rú)r rG)rÚfindrr{rJrÂ)rhZpeerÚleftÚrightÚpartsrr1rrrr‰Us   r‰cCs’|dd…dkr t|ƒ‚|dd…dkrdSd}d}t|ƒ}||krG||}|d}|dkr?||ks8||dkr; |S|d}||}||ks"|S) z¤Parse the '257' response for a MKD or PWD request. This is a response to a MKD or PWD request: a directory name. Returns the directoryname in the 257 reply.Nr^rÃrGz "rr ú")rrJ)rhr¾rNÚnrirrrrÆjs$þùrÆcCs t|ƒdS)z+Default retrlines callback to print a line.N)r>)rUrrrrž€s ržrÚIc Cs´|s|}d|}| |¡| |¡t| d¡ƒ\}}|jr!|}n|j ¡d}| ||¡| d|¡}|dd…dvr?t‚| d|¡} | dd…dvrPt‚| ¡| ¡dS) z+Copy file from one FTP-instance to another.zTYPE r…rzSTOR Nr^>rŒZ125úRETR ) rwr†rur‡r'rˆr~rrk) ÚsourceZ sourcenameÚtargetZ targetnamer«rŠZ sourceportZ sourcehostZtreplyZsreplyrrrÚftpcp…s$    rýc Csàttjƒdkrttjƒt d¡ddl}d}d}tjddkr/|d}tjd=tjddks tjddd…dkrGtjddd…}tjd=tjd}t|ƒ}|  |¡d}}}z| |¡}Wnt yu|durstj   d¡Ynwz |  |¡\}}}Wnty�tj   d ¡Ynw| |||¡tjdd…D]K} | dd…d kr²| | dd…¡qž| dd…dkrÒd } | dd…rÌ| d | dd…} | | ¡} qž| d krÞ| |j ¡qž| d| tjj d¡qž| ¡dS)z‚Test program. Usage: ftp [-d] [-r[file]] host [-l[dir]] [-d[dir]] [-p] [file] ... -d dir -l list -p password rrNr z-dz-rrz5Could not open account file -- using anonymous login.z$No account -- using anonymous login.z-lZCWDr¦z-prúi)rJr3Úargvr>ÚtestrÊÚexitÚnetrcrrCr)ÚstderrÚwriteZauthenticatorsÚKeyErrorrr­rurFrDrœÚstdoutr() rr=ZrcfilerZftpZuseridr!r"Znetrcobjr:rtrhrrrrÿ¤sZ  þ     €þ ÿþ   ÿ rÿÚ__main__)rrù)%rÊr3r5rÚ__all__rorËrÌÚ Exceptionr rrrrr)r*rrQrnrrÔÚ ImportErrorr–rÛrÎr§ZSSLErrorrår�rîr†r‰rÆržrýrÿrrrrrÚsT&  ^  ÿ } 9 ÿ