m "Ec@sdZdklZdklZlZlZdkZdkZdk l Z dk l Z dk l Z dklZdklZdkZd klZdkZdkZdkZd efd YZd Zee_d fdYZdfdYZdefdYZdS(s(ZServer FTP Channel for use the medusa's ftp server. FTP Service for Zope. This server allows FTP connections to Zope. In general FTP is used to manage content. You can: * Create and delete Folders, Documents, Files, and Images * Edit the contents of Documents, Files, Images In the future, FTP may be used to edit object properties. FTP Protocol The FTP protocol for Zope gives Zope objects a way to make themselves available to FTP services. See the 'lib/python/OFS/FTPInterface.py' for more details. FTP Permissions FTP access is controlled by one permission: 'FTP access' if bound to a role, users of that role will be able to list directories, and cd to them. Creating and deleting and changing objects are all governed by existing Zope permissions. Permissions are to a certain extent reflected in the permission bits listed in FTP file listings. FTP Authorization Zope supports both normal and anonymous logins. It can be difficult to authorize Zope users since they are defined in distributed user databases. Normally, all logins will be accepted and then the user must proceed to 'cd' to a directory in which they are authorized. In this case for the purpose of FTP limits, the user is considered anonymous until they cd to an authorized directory. Optionally, users can login with a special username which indicates where they are defined. Their login will then be authenticated in the indicated directory, and they will not be considered anonymous. The form of the name is '@' where path takes the form '[/...]' For example: 'amos@Foo/Bar' This will authenticate the user 'amos' in the directory '/Foo/Bar'. In addition the user's FTP session will be rooted in the authenticated directory, i.e. they will not be able to cd out of the directory. The main reason to use the rooted FTP login, is to allow non-anonymous logins. This may be handy, if for example, you disallow anonymous logins, or if you set the limit for simultaneous anonymous logins very low. (shandle(s ftp_channels ftp_servers recv_channelN(sfilesys(s make_response(s FTPRequest(srequestCloseOnExec(sStringIO(s guess_typetzope_ftp_channelcBstZdZdZdZdZdZddZeZdZ dZ ddZ dd Z d Z d Zd Zd ZdZeZdZdZdZdZdZdZddZdZdZdZdZdZdZdZ dZ!dZ"e"Z#d Z$d!Z%e%Z&d"Z'd#Z(d$Z)d%Z*d&Z+d'Z,RS((s-Passes its commands to Zope, not a filesystemiicCsQti||||t|||_d|_d|_ d|_ h|_ dS(Ntt/( t ftp_channelt__init__tselftservertconntaddrtrequestCloseOnExectmoduletuseridtpasswordtpathtcookies(RRRRR ((t0/data/zmath/zope/lib/python/ZServer/FTPServer.pyR[s     cGsQtii|}tii|}tidjo|itid}n|S(NR(tosR tjointargstnormpathtseptreplace(RRR ((Rt _join_pathsds cCs)|ii||o|indS(N(Rt producer_fifotpushtproducertsendt initiate_send(RRR((RRmscCs|i|ddS(s$give name list of files in directoryiN(Rt get_dir_listtline(RR((Rtcmd_nlstyscCs|i|ddS(sgive list files in a directoryiN(RRR(RR((Rtcmd_list}sc CsNd|_d|_t|djo|di}ng}g}xgt t|D]S}||}|i ddjp|i ddjo||_d||RCRDRAR?((RR7s,      "    cCsXt||i|i|i|d}t|dd||}t |i ||dS(schange working directoryitCWDN( R6Rtcwd_completionRR RR8R9R:R;R (RRR:R8((Rtcmd_cwds  cCs|i}|djo|i}t|dtdjo|iddSq|pd|_|id|i o|i dj o d|_ qn,|d jo|id n|iddS( scwd completion callbackiiRs550 No such directory.NRs250 CWD command successful.R<iis530 Unauthorized.(ii( R8R=R>R@tlistingRBRRJR R<R R&(RR R8R>RP((RRNs      cCs|iddS(s-change to parent of current working directorys..N(Ns..(RROR&(RR((Rtcmd_cdupscCs|id|idS(s#print the current working directorys"257 "%s" is the current directory.N(RRJR (RR((Rtcmd_pwdscCsvt|djo!|iidi|dSnt||i}t |dd||}t |i ||dS(s#show last modification time of fileit NitMDTM( R)RRtcommandtnot_understoodRR6tmdtm_completionR8R9R:R;R (RRR:R8((Rtcmd_mdtmsc Cs|i}|djoa|iti}ti|}|i d|d|d|d|d|d|dfn,|d jo|i d n|i d dS(Nis213 %4d%02d%02d%02d%02d%02diiiiiiiis530 Unauthorized.s)550 Error getting file modification time.(ii( R8R=R>R@tstattST_MTIMEtmtimettimetgmtimeRRJ(RR8R>R[((RRWs  ? cCsvt|djo!|iidi|dSnt||i}t |dd||}t |i ||dS(sreturn size of fileiRSNitSIZE( R)RRRURVRR6tsize_completionR8R9R:R;R (RRR:R8((Rtcmd_sizescCs|i}|djo"|id|itinJ|d jo|idn,|djo|idn|iddS( Nis213 %diis530 Unauthorized.is550 No such file or directory.s550 Error getting file size.(ii(R8R=R>RRJR@RYtST_SIZE(RR8R>((RR_s  "  cCst|djo|idi|dSnt||i|d}|ii |_ t |dd||}|i djod|i |id|i o|ii|i qn%x!|i D]}|ii|qWd|_ |ii|id|i|i|fn,|d jo|idn|iddS( Niiis1150 Opening %s mode data connection for file '%s'iis530 Unauthorized.s550 Error opening file.(ii(R8R=R>RRGt_wroteRHtpush_with_producertasynchattsimple_producertbodyt _bodyproducerRhRR&RIRJRKRLtfile(RRrR8R>R((RRe4s     #    % twbcCst|djo|idi|dSn&|iod}|iddSnt|i|d}|id|i |i |df|i |dS(s store a fileiRSNis%553 restart on STOR not yet supportedis 150 Opening %s connection for %s( R)RRRdRRiRJtContentReceivert stor_callbacktfdRKRLtmake_recv_channel(RRtmodeRvRi((Rtcmd_storUs  %c CsJt||i}t|d||d|d|}t |i ||dS(s0callback to do the STOR, after we have the inputtSTORtstdintsizeN( R6Rtstor_completionR8R9R tdataR|R:R;R (RR R~R|R:R8((RRuls cCsx|i}|d jo|iiidn8|d jo|iiidn|iiid |iidS( Niiii.s226 Transfer complete.iis 553 Permission denied on server.s426 Error creating file.(iiii.(ii(R8R=R>RRHtchannelRJtclose(RR8R>((RR}ss   cCst|djo|idi|ni|d|_tii|i\}}t ||i }t|d|f||}t|i||dS(s rename fromiRSitRNFRN(R)RRRdRtfromfileRR R*tpathftidfR6trnfr_completionR8R9R:R;R (RRR:RRR8((Rtcmd_rnfr~s cCsB|i}|djo|idn|id|idS(Nis350 RNFR command successful.s"550 %s: no such file or directory.(R8R=R>RRJR(RR8R>((RRs  cCst|djo|idi|dSntii|i\}}tii|d\}}t ||i}t|d||f||}t|i||dS(NiRSitRNTO(R)RRRdRRR R*RRRtpathttidtR6trnto_completionR8R9R:R;R (RRRR:R8RRR((Rtcmd_rntoscCs;|i}|djo|idn|iddS(Nis250 RNTO command successful.s550 error renaming file.(R8R=R>RRJ(RR8R>((RRs  cCst|djo!|iidi|dSntii|d\}}t ||i }t |d|f||}t|i||dS(NiRSitDELE(R)RRRURVRRR R*RCR6tdele_completionR8R9R:R;R (RRR:R8R RC((Rtcmd_delescCsr|i}|djo*|iiddjo|idn,|d jo|idn|iddS( Nis Not Deletableis250 DELE command successful.iis530 Unauthorized.s550 Error deleting file.(ii(R8R=R>RpR/RRJ(RR8R>((RRs  & cCst|djo!|iidi|dSntii|d\}}t ||i }t |d|f||}t|i||dS(NiRSitMKD(R)RRRURVRRR R*RCR6tmkd_completionR8R9R:R;R (RRR:R8R RC((Rtcmd_mkdscCsY|i}|djo|idn,|djo|idn|iddS(Nis257 MKD command successful.iis530 Unauthorized.s550 Error creating directory.(ii(R8R=R>RRJ(RR8R>((RRs    cCst|djo!|iidi|dSntii|d\}}t ||i }t |d|f||}t|i||dS(NiRSitRMD(R)RRRURVRRR R*RCR6trmd_completionR8R9R:R;R (RRR:R8R RC((Rtcmd_rmdscCsr|i}|djo*|iiddjo|idn,|d jo|idn|iddS( Nis Not Deletableis250 RMD command successful.iis530 Unauthorized.s550 Error removing directory.(ii(R8R=R>RpR/RRJ(RR8R>((RRs  & cCsKt|djo|d|_|idn|idi|dS(sspecify user nameis331 Password required.RSN(R)RRR RJRdR(RR((Rtcmd_users  cCs't|djo d}n |d}||_|iid}|djoa|ii i |o0|i dd|_ d|_ |idq#|i d|int|i|d}|i| |_d |_ t||i|id |}t|d ||}t|i||d S( sspecify passwordiRit@is230 Login successful.sSuccessful login.s+421 User limit reached. Closing connection.RtPASSN(R)RtpwRR R R/R-Rtlimitert check_limitRJt authorizedR<tlog_infoRIR R&R6tpass_completionRR8R9R:R;R (RRRR-R:R R8((Rtcmd_passs*          cCs|i}|djo|iii|p|i|iddSn|i }t |dt djo|iddSn|pd|_ d|_ |idjo d|_n|id |id n|iddS( Nis+421 User limit reached. Closing connection.iRs530 Unauthorized.RiR<sSuccessful login.s230 Login successful.(R8R=R>RRRRRIRJR@RPRBR RR R<R(RR R8R>RP((RRs"         cCs|iddS(Ns502 Command not implemented.(RRJ(RR((Rtcmd_appescCs|iddS(Ns0211-Extensions supported: MDTM SIZE 211 END(RRJ(RR((Rtcmd_feats(-t__name__t __module__t__doc__t read_onlyR<RRRRmRRRR4R7RORNRQRRtcmd_xpwdRXRWR`R_RkReRyRuR}RRRRRRRtcmd_xmkdRRtcmd_xrmdRRRRRR(((RRUsV     %        !          cCsO|ii}|ii|ii|ii|i i d|_ dS(s+response and closure of channel is delayed.cCsdS(Ni((((Rt*sN( RRRtsttotal_files_int incrementttotal_bytes_intbytes_intas_longRvRtreadable(RR((Rt handle_close$s    RtcBs)tZdZdZdZdZRS(s4Write-only file object used to receive data from FTPcGs2dkl}|d|_||_||_dS(N(s TemporaryFilesw+b(ttempfilet TemporaryFileRR~tcallbackR(RRRR((RR2s  cCs|ii|dS(N(RR~twrite(RR~((RR8scCs^|ii}|iid|i|i|f}|i}d|_d|_||dS(Ni( RR~ttellR|tseekRRtcR&(RRRR|((RR;s   (RRRRRR(((RRt/s   t FTPLimitercBs)tZdZddddZdZRS(sURudimentary FTP limits. Helps prevent denial of service attacks. It works by limiting the number of simultaneous connections by userid. There are three limits, one for anonymous connections, and one for authenticated logins. The total number of simultaneous anonymous logins my be less than or equal to the anonymous limit. Each authenticated user can have up to the user limit number of simultaneous connections. The total limit is the maximum number of simultaneous connections of any sort. Do *not* set the total limit lower than or equal to the anonymous limit.i iicCs||_||_||_dS(N(t anon_limitRt user_limitt total_limit(RRRR((RRPs  cCs5d}d}|iox`tiiD]O}t|do9|i |i jo&|d}|io|d}quq&q&W||i jodSqnxitiiD]X}t|doB|i |i jo/|d}|i |i jo|d}qqqW||ijodSn||ijodSndS(sCheck to see if the user has exhausted their limit or not. Check for existing channels with the same userid and the same ftp server.iRiN(ttotalt class_totalRR<tasyncoret socket_maptvaluestexisting_channelthasattrRRRR&R RR(RRRRR((RRUs, #   # (RRRRR(((RREs t FTPServercBsktZdZeZeddZdZdZdZ ddZ dZ d Z d Z d ZRS( sFTP server for Zope.i iicOsdd|_ti|d||d|_||_|idt i t i |i |i fdS(Niis0FTP server started at %s Hostname: %s Port: %d( Rtshutupt ftp_serverRR&RtkwR RR\tctimethostnametport(RR RR((RRxs    cCs,|djo|id|indS(Nisclosing FTP to new connections(tphaseRRR(RRttime_in_this_phase((Rtclean_shutdown_controls  tinfocCs,|iodSntii|||dS(N(RRRt dispatcherRtmessageRB(RRRB((RRs cCs'tii|||t|idS(N(RRt create_socketRtfamilyRBR tsocket(RRRB((RRscCsyy|i\}}Wntj o dSnX|ii|id|d|df|i||||i dS(NsIncoming connection from %s:%dii( RtacceptRRt TypeErrorttotal_sessionsRRtftp_channel_classR (RRR((Rt handle_accepts  cCs dkl}tti|jS(N(sCONNECTION_LIMIT(tZServertCONNECTION_LIMITR)RR(RR((RRs cCsd|_|ii|S(Ni(Rt acceptingRtlistentnum(RR((RRs (RRRRRRRRRRRRRRR(((RRqs     (RtPubCoreR;tmedusa.ftp_serverRRt recv_channelRRntmedusaREt FTPResponseR6R9RR t cStringIOtStringIORt mimetypest guess_typetmarshalRYR\RRRtRR(RRRnRRYRRR6RRRRR9RER\RtR;RRRR ((RR!As(             ,