o ?Og@sNdZddlZddlZddlmZgdZdZdZdZGdd d eZ Gd d d e Z Gd d d e Z Gddde Z Gddde Z e eefZdZdZGdddZzddlZWn eycdZYnwejZGdddeZede eeejfZdaddZdaddZddZddZ d d!Z!d)d$d%Z"d&d'Z#e$d(kre#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@seZdZdZdZdZeZeZ dZ dZ dZ dZ dZddddedfddd d Zd d Zd dZd]ddZddZddZeZddZddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Z d*d+Z!d,d-Z"d.d/Z#d0d1Z$d2d3Z%d^d4d5Z&d^d6d7Z'd_d8d9Z(d`d;d<Z)d^d=d>Z*dad?d@Z+d^dAdBZ,dCdDZ-dEdFZ.dGdHZ/dgfdIdJZ0dKdLZ1dMdNZ2dOdPZ3dQdRZ4dSdTZ5dUdVZ6dWdXZ7dYdZZ8d[d\Z9dS)bruAn 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. rNTFutf-8encodingcCs>||_||_||_|r|||r||||dSdSdS)zInitialization 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)rsource_addresstimeoutconnectlogin)selfhostuserpasswdacctrrrrrr__init__ms z FTP.__init__cCs|SNrrrrr __enter__}sz FTP.__enter__c Gsf|jdur1z z|Wn ttfyYnwW|jdur$|dSdS|jdur0|wwdSr$)sockquitOSErrorEOFErrorclose)rargsrrr__exit__s     z FTP.__exit__cCs|dkr||_|dkr||_|dkr||_|jdur!|js!td|dur(||_td||j|jtj|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.connectrrr)rportr ValueErrorrsysauditsocketcreate_connectionr'familyafmakefilerfilegetrespwelcome)rrr1rrrrrrs$  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*) debuggingprintsanitizer<r%rrr getwelcomeszFTP.getwelcomecC ||_dS)zSet 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=)rlevelrrrset_debuglevels zFTP.set_debuglevelcCrA)zUse 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)rvalrrrset_pasvs z FTP.set_pasvcCsJ|dddvr!t|d}|ddd|d||d}t|S)N>zpass PASS r*)lenrstriprepr)rsirrrr?s$z FTP.sanitizecCs`d|vsd|vr tdtd|||t}|jdkr$td|||j| |j dS)N  z4an illegal newline character should not be containedzftplib.sendcmdr z*put*) r2r3r4CRLFr=r>r?r'sendallencoderrlinerrrputlines z FTP.putlinecCs$|jr td||||dS)Nz*cmd*)r=r>r?rVrTrrrputcmdsz FTP.putcmdcCs|j|jd}t||jkrtd|j|jdkr$td|||s(t|ddt kr8|dd}|S|ddt vrF|dd}|S)Nr got more than %d bytesz*get*) r:readlinemaxlinerJr r=r>r?r*rQrTrrrgetlines   z FTP.getlinecCsf|}|dddkr1|dd} |}|d|}|dd|kr0|dddkr0 |Sq|S)N-r rP)r])rrUcodeZnextlinerrr getmultilines  zFTP.getmultilinecCsl|}|jrtd|||dd|_|dd}|dvr"|S|dkr*t||dkr2t|t|)Nz*resp*r^r >31245)rbr=r>r?Zlastresprrr)rrespcrrrr;s z FTP.getrespcCs$|}|dddkrt||S)z%Expect a response beginning with '2'.Nr re)r;rrrhrrrvoidrespsz FTP.voidrespcCsTdt}|jdkrtd|||j|t|}|dddvr(t||S)zAbort 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^Z226Z225Z426) B_CRLFr=r>r?r'rRMSG_OOBrbrrrUrhrrraborts z FTP.abortcC|||S)z'Send a command and return the response.)rWr;rcmdrrrsendcmd z FTP.sendcmdcCrr)z8Send a command and expect a response beginning with '2'.)rWrkrsrrrvoidcmdrvz FTP.voidcmdcCsB|d}t|dt|dg}||}dd|}||S)zUSend a PORT command with the current host and the given port number. .zPORT ,)splitrLjoinrw)rrr1ZhbytesZpbytesbytesrtrrrsendport s  z FTP.sendportcCsbd}|jtjkr d}|jtjkrd}|dkrtddt||t|dg}dd|}||S)zESend an EPRT command with the current host and the given port number.rr zunsupported address familyrzEPRT |)r8r5AF_INETZAF_INET6rrLr|rw)rrr1r8Zfieldsrtrrrsendeprt*s   z FTP.sendeprtcCsltjd|jdd}|d}|jd}|jtjkr#|||}n|||}|jt ur4| |j|S)z3Create a new socket and send a PORT command for it.)rrr )r7Zbacklogr) r5Z create_serverr8Z getsocknamer'rr~rrr settimeout)rr'r1rrhrrrmakeport7s     z FTP.makeportcCsh|jtjkr#t|d\}}|jr|}||fS|jd}||fSt|d|j\}}||fS)z (address, port)PASVrZEPSV) r8r5rparse227rutrust_server_pasv_ipv4_addressr'Z getpeernameparse229)rZuntrusted_hostr1rrrrmakepasvDs z FTP.makepasvc Cs>d}|jrF|\}}tj||f|j|jd}z&|dur#|d|||}|ddkr2|}|ddkrrr`z anonymous@zUSER rrcrHACCT rerur)rr r!r"rhrrrrs    z FTP.loginr cCs|d|||:} ||}|sn||q tdur1t|tr;|Wd|SWd|SWd|S1sHwY|S)aRetrieve 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)rwrZrecv _SSLSocket isinstanceunwraprk)rrtcallback blocksizerrdatarrr retrbinarys(          zFTP.retrbinaryc Cs<|durt}|d}||}|jd|jd]} ||jd}t||jkr1td|j|j dkr=t dt ||s@n"|d dt krO|dd }n|d dd kr]|dd }||qt durot|t ro|Wdn1sywYWd|SWd|S1swY|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. NTYPE Ar0rr rXrz*retr*rYrZrP) print_linerurr9rr[r\rJr r=r>rLrQrrrrk)rrtrrhrfprUrrr retrliness<     ( z FTP.retrlinescCs|d|||A} ||}|sn |||r ||q tdur8t|trB|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. rr N)rwrreadrRrrrrk)rrtrrrrrbufrrr storbinarys,           zFTP.storbinarycCs|d||j} ||jd}t||jkr"td|j|s%n$|ddtkr=|dtvr9|dd}|t}|||rH||q tdur`t |trj| 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. rr rXrYNrZ) rwrr[r\rJr rnrRrrrrk)rrtrrrrrrr storliness6      z FTP.storlinescCsd|}||S)zSend new account name.rrw)rZpasswordrtrrrr"s zFTP.acctcGs0d}|D]}|d|}qg}|||j|S)zBReturn a list of files in a given directory (default the current).ZNLST )rappend)rr,rtargfilesrrrnlst#s zFTP.nlstcGshd}d}|ddrt|dtdkr|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,rtfuncrrrrdir,s  zFTP.dirc cs|r|dd|d|rd|}nd}g}|||j|D].}|td\}}}i} |dddD]} | 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 %sZMLSDrNrZ=) rur|rrrKrQ partitionr{lower) rpathZfactsrtlinesrUZ facts_found_nameentryZfactkeyvaluerrrmlsd;s    zFTP.mlsdcCs0|d|}|ddkrt||d|S)zRename a file.zRNFR rrczRNTO )rurrw)rZfromnameZtonamerhrrrrenameWs z FTP.renamecCs*|d|}|dddvr|St|)zDelete a file.zDELE Nr^>Z250Z200r)rfilenamerhrrrdelete^sz FTP.deletec Csp|dkr)z|dWSty(}z|jddddkrWYd}~n d}~ww|dkr/d}d |}||S) zChange to a directory.z..ZCDUPrNr^500rrxzCWD )rwrr,)rdirnamemsgrtrrrcwdfs   zFTP.cwdcCs:|d|}|dddkr|dd}t|SdS)zRetrieve the size of a file.zSIZE Nr^Z213)rustripint)rrrhrMrrrrss zFTP.sizecCs$|d|}|dsdSt|S)z+Make a directory, return its full pathname.zMKD 257rrw startswithparse257)rrrhrrrmkd{s zFTP.mkdcCs|d|S)zRemove a directory.zRMD r)rrrrrrmdszFTP.rmdcCs |d}|ds dSt|S)z!Return current working directory.ZPWDrrrrjrrrpwds  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=rFTP_PORTr1MAXLINEr\r'r:r<rDrrr#r&r-rr@rCdebugrFr?rVrWr]rbr;rkrqrurwr~rrrrrrrrrrr"rrrrrrrrrrr(r+rrrrrJsr      7    #     rc seZdZdZejZdddddddedf ddfdd Zdfd d Z d d Z d dZ ddZ ddZ dfdd ZddZZS)FTP_TLSaA 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 |||||| | ddS) Nz4context and keyfile arguments are mutually exclusivez5context and certfile arguments are mutually exclusiverzAkeyfile and certfile are deprecated, use a custom context insteadr)certfilekeyfileFr) r2warningswarnDeprecationWarningrrsslZ_create_stdlib_context ssl_versioncontext_prot_psuperr#) rrr r!r"rrrrrrr __class__rrr#s* zFTP_TLS.__init__Tcs*|r t|jtjs |t|||Sr$)rr'r SSLSocketauthrr)rr r!r"Zsecurerrrrsz FTP_TLS.logincCsft|jtjr 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 SSLZserver_hostnamer0)moder)rr'rrr2rZ PROTOCOL_TLSrwr wrap_socketrr9rr:rjrrrrs   z FTP_TLS.authcCs0t|jtjs td|d}|j|_|S)z/Switch back to a clear-text control connection.z not using TLSZCCC)rr'rrr2rwrrjrrrcccs   z FTP_TLS.ccccCs|d|d}d|_|S)zSet up secure data connection.zPBSZ 0zPROT PTrwrrjrrrprot_ps zFTP_TLS.prot_pcCs|d}d|_|S)z"Set up clear text data connection.zPROT CFrrjrrrprot_cs zFTP_TLS.prot_ccs2t||\}}|jr|jj||jd}||fS)Nr)rrrrrr)rrtrrrrrrrs zFTP_TLS.ntransfercmdcCs8dt}|j||}|dddvrt||S)Nrlr^rm)rnr'rRrbrrprrrrqs  z FTP_TLS.abort)rrrTr$)rrrrrZPROTOCOL_TLS_CLIENTrrr#rrrrrrrq __classcell__rrrrrs   rcCs\|dddkr t|tdurddl}|d|j|jBat|}|s'dSt|dS)zParse 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^rrz150 .* \((\d+) bytes\)r ) r_150_rerecompile IGNORECASEASCIImatchrgroup)rhrmrrrr.s  rcCs|dddkr t|tdurddl}|d|jat|}|s&t||}d|dd}t |dd>t |d }||fS) zParse 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_rerrrsearchrgroupsr|r)rhrrZnumbersrr1rrrrBs rcCs|dddkr t||d}|dkrt||d|d}|dkr)t|||d||dkr9t|||d|||d}t|dkrRt||d}t|d}||fS) zParse 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)rfindrr{rJr)rhZpeerleftrightpartsrr1rrrrUs   rcCs|dddkr t||dddkrdSd}d}t|}||krG||}|d}|dkr?||ks8||dkr; |S|d}||}||ks"|S) zParse 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^rrGz "rr ")rrJ)rhrrNnrirrrrjs$rcCs t|dS)z+Default retrlines callback to print a line.N)r>)rUrrrrs rrIc Cs|s|}d|}||||t|d\}}||||d|}|dddvr2t|d|}|dddvrCt||dS)z+Copy file from one FTP-instance to another.zTYPE rzSTOR Nr^>rZ125RETR )rwrrur~rrk) sourceZ sourcenametargetZ targetnamerZ sourcehostZ sourceportZtreplyZsreplyrrrftpcps    rc Csttjdkrttjtdddl}d}d}tjddkr/|d}tjd=tjddks tjddddkrGtjddd}tjd=tjd}t|}| |d}}}z||}Wnt yu|durstj dYnwz | |\}}}Wntytj d Ynw||||tjddD]K} | ddd kr|| ddq| dddkrd } | ddr| d | dd} || } q| d kr||j q|d| tjj dq|dS)zTest 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-lZCWDrz-pri)rJr3argvr>testrexitnetrcrrCr)stderrwriteZauthenticatorsKeyErrorrrrurFrDrstdoutr() rr=ZrcfilerZftpZuseridr!r"Znetrcobjr:rtrhrrrrsZ            r__main__)rr)%rr3r5r__all__rorr Exceptionr rrrrr)r*rrQrnrr ImportErrorrrrrZSSLErrorrrrrrrrrrrrrrrsT&  ^   } 9