|
|
|
@ -1354,6 +1354,11 @@ class AbstractedFS:
|
|
|
|
|
|
|
|
|
|
# --- FTP
|
|
|
|
|
|
|
|
|
|
class FTPExceptionSent(Exception):
|
|
|
|
|
"""An FTP exception that FTPHandler has processed
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
class FTPHandler(asynchat.async_chat):
|
|
|
|
|
"""Implements the FTP server Protocol Interpreter (see RFC-959),
|
|
|
|
|
handling commands received from the client on the control channel.
|
|
|
|
@ -1453,6 +1458,14 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
self._epsvall = False
|
|
|
|
|
self.__in_dtp_queue = None
|
|
|
|
|
self.__out_dtp_queue = None
|
|
|
|
|
|
|
|
|
|
self.__errno_responses = {
|
|
|
|
|
errno.EPERM: 553,
|
|
|
|
|
errno.EINVAL: 504,
|
|
|
|
|
errno.ENOENT: 550,
|
|
|
|
|
errno.EREMOTE: 450,
|
|
|
|
|
errno.EEXIST: 521,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# mlsx facts attributes
|
|
|
|
|
self.current_facts = ['type', 'perm', 'size', 'modify']
|
|
|
|
@ -1815,6 +1828,58 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
|
|
|
|
|
# --- connection
|
|
|
|
|
|
|
|
|
|
def try_as_current_user(self, function, args=None, kwargs=None, line=None, errno_resp=None):
|
|
|
|
|
"""run function as current user, auto-respond in exceptions
|
|
|
|
|
@param args,kwargs the arguments, in list and dict respectively
|
|
|
|
|
@param errno_resp a dictionary of responses to IOError, OSError
|
|
|
|
|
"""
|
|
|
|
|
if errno_resp:
|
|
|
|
|
eresp = self.__errno_responses.copy()
|
|
|
|
|
eresp.update(errno_resp)
|
|
|
|
|
else:
|
|
|
|
|
eresp = self.__errno_responses
|
|
|
|
|
|
|
|
|
|
uline = ''
|
|
|
|
|
if line:
|
|
|
|
|
uline = ' "%s"' % _to_unicode(line)
|
|
|
|
|
try:
|
|
|
|
|
if args is None:
|
|
|
|
|
args = ()
|
|
|
|
|
if kwargs is None:
|
|
|
|
|
kwargs = {}
|
|
|
|
|
return self.run_as_current_user(function, *args, **kwargs)
|
|
|
|
|
except NotImplementedError, err:
|
|
|
|
|
cmdname = function.__name__
|
|
|
|
|
why = err.args[0] or 'Not implemented'
|
|
|
|
|
self.log('FAIL %s() not implemented: %s.' %(cmdname, why))
|
|
|
|
|
self.respond('502 %s.' %why)
|
|
|
|
|
raise FTPExceptionSent(why)
|
|
|
|
|
except EnvironmentError, err:
|
|
|
|
|
cmdname = function.__name__
|
|
|
|
|
try:
|
|
|
|
|
logline(traceback.format_exc())
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
ret_code = eresp.get(err.errno, '451')
|
|
|
|
|
why = (err.strerror) or 'Error in command'
|
|
|
|
|
self.log('FAIL %s() %s errno=%s: %s.' %(cmdname, uline, err.errno, why))
|
|
|
|
|
self.respond('%s %s.' % (str(ret_code), why))
|
|
|
|
|
|
|
|
|
|
raise FTPExceptionSent(why)
|
|
|
|
|
except Exception, e:
|
|
|
|
|
cmdname = function.__name__
|
|
|
|
|
try:
|
|
|
|
|
logerror(traceback.format_exc())
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
why = (err.args and err.args[0]) or 'Exception'
|
|
|
|
|
self.log('FAIL %s() %s Exception: %s.' %(cmdname, uline, why))
|
|
|
|
|
self.respond('451 %s.' % why)
|
|
|
|
|
raise FTPExceptionSent(why)
|
|
|
|
|
|
|
|
|
|
def get_crdata2(self, *args, **kwargs):
|
|
|
|
|
return self.try_as_current_user(self.fs.get_crdata, args, kwargs, line=args[0])
|
|
|
|
|
|
|
|
|
|
def _make_eport(self, ip, port):
|
|
|
|
|
"""Establish an active data channel with remote client which
|
|
|
|
|
issued a PORT or EPRT command.
|
|
|
|
@ -2037,18 +2102,12 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
line = ''
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='list')
|
|
|
|
|
iterator = self.run_as_current_user(self.fs.get_list_dir, datacr)
|
|
|
|
|
except IOError, err:
|
|
|
|
|
datacr = self.get_crdata2(line, mode='list')
|
|
|
|
|
iterator = self.try_as_current_user(self.fs.get_list_dir, (datacr,))
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
self.respond('550 %s.'% err.strerror)
|
|
|
|
|
return
|
|
|
|
|
except OSError, err:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL LIST "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
self.log('OK LIST "%s". Transfer starting.' % line)
|
|
|
|
|
producer = BufferedIteratorProducer(iterator)
|
|
|
|
@ -2066,11 +2125,11 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='list')
|
|
|
|
|
datacr = self.get_crdata2(line, mode='list')
|
|
|
|
|
if not datacr:
|
|
|
|
|
datacr = ( None, None, None )
|
|
|
|
|
if self.fs.isdir(datacr[1]):
|
|
|
|
|
nodelist = self.run_as_current_user(self.fs.listdir, datacr)
|
|
|
|
|
nodelist = self.try_as_current_user(self.fs.listdir, (datacr,))
|
|
|
|
|
else:
|
|
|
|
|
# if path is a file we just list its name
|
|
|
|
|
nodelist = [datacr[1],]
|
|
|
|
@ -2081,15 +2140,8 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
listing.append(nl.path[-1])
|
|
|
|
|
else:
|
|
|
|
|
listing.append(nl.path) # assume string
|
|
|
|
|
except IOError, err:
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
self.respond('550 %s.'% err.strerror)
|
|
|
|
|
return
|
|
|
|
|
except OSError, err:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL NLST "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
@ -2116,16 +2168,14 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
line = ''
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='list')
|
|
|
|
|
datacr = self.get_crdata2(line, mode='list')
|
|
|
|
|
perms = self.authorizer.get_perms(self.username)
|
|
|
|
|
iterator = self.run_as_current_user(self.fs.format_mlsx, datacr[0], datacr[1].parent,
|
|
|
|
|
[datacr[1],], perms, self.current_facts, ignore_err=False)
|
|
|
|
|
iterator = self.try_as_current_user(self.fs.format_mlsx, (datacr[0], datacr[1].parent,
|
|
|
|
|
[datacr[1],], perms, self.current_facts), {'ignore_err':False})
|
|
|
|
|
data = ''.join(iterator)
|
|
|
|
|
except EnvironmentError, err:
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL MLST "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
# since TVFS is supported (see RFC-3659 chapter 6), a fully
|
|
|
|
@ -2147,19 +2197,17 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='list')
|
|
|
|
|
datacr = self.get_crdata2(line, mode='list')
|
|
|
|
|
# RFC-3659 requires 501 response code if path is not a directory
|
|
|
|
|
if not self.fs.isdir(datacr[1]):
|
|
|
|
|
err = 'No such directory'
|
|
|
|
|
self.log('FAIL MLSD "%s". %s.' %(line, err))
|
|
|
|
|
self.respond("501 %s." %err)
|
|
|
|
|
return
|
|
|
|
|
listing = self.run_as_current_user(self.fs.listdir, datacr)
|
|
|
|
|
except OSError, err:
|
|
|
|
|
listing = self.try_as_current_user(self.fs.listdir, (datacr,))
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL MLSD "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
perms = self.authorizer.get_perms(self.username)
|
|
|
|
@ -2175,19 +2223,10 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
"""
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='file')
|
|
|
|
|
fd = self.run_as_current_user(self.fs.open, datacr, 'rb')
|
|
|
|
|
except OSError, err:
|
|
|
|
|
datacr = self.get_crdata2(line, mode='file')
|
|
|
|
|
fd = self.try_as_current_user(self.fs.open, (datacr, 'rb'))
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL RETR "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
except IOError, err:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = err.strerror
|
|
|
|
|
self.log('FAIL RETR "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if self.restart_position:
|
|
|
|
@ -2230,23 +2269,12 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line,mode='create')
|
|
|
|
|
except OSError, err:
|
|
|
|
|
datacr = self.get_crdata2(line,mode='create')
|
|
|
|
|
if self.restart_position:
|
|
|
|
|
mode = 'r+'
|
|
|
|
|
fd = self.try_as_current_user(self.fs.create, (datacr, datacr[2], mode + 'b'))
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL %s "%s". %s.' %(cmd, line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if self.restart_position:
|
|
|
|
|
mode = 'r+'
|
|
|
|
|
try:
|
|
|
|
|
fd = self.run_as_current_user(self.fs.create, datacr, datacr[2], mode + 'b')
|
|
|
|
|
except IOError, err:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL %s "%s". %s.' %(cmd, line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if self.restart_position:
|
|
|
|
@ -2301,16 +2329,19 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if line:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='create')
|
|
|
|
|
# TODO
|
|
|
|
|
datacr = self.get_crdata2(line, mode='create')
|
|
|
|
|
# TODO
|
|
|
|
|
else:
|
|
|
|
|
# TODO
|
|
|
|
|
# TODO
|
|
|
|
|
basedir = self.fs.ftp2fs(self.fs.cwd, datacr)
|
|
|
|
|
prefix = 'ftpd.'
|
|
|
|
|
try:
|
|
|
|
|
fd = self.run_as_current_user(self.fs.mkstemp, prefix=prefix,
|
|
|
|
|
dir=basedir)
|
|
|
|
|
except IOError, err:
|
|
|
|
|
fd = self.try_as_current_user(self.fs.mkstemp, kwargs={'prefix':prefix,
|
|
|
|
|
'dir': basedir}, line=line )
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
return
|
|
|
|
|
except IOError, err: # TODO
|
|
|
|
|
# hitted the max number of tries to find out file with
|
|
|
|
|
# unique name
|
|
|
|
|
if err.errno == errno.EEXIST:
|
|
|
|
@ -2513,22 +2544,15 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
# Search for official references about this behaviour.
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line,'cwd')
|
|
|
|
|
self.run_as_current_user(self.fs.chdir, datacr)
|
|
|
|
|
datacr = self.get_crdata2(line,'cwd')
|
|
|
|
|
self.try_as_current_user(self.fs.chdir, (datacr,), line=line, errno_resp={2: 530})
|
|
|
|
|
cwd = self.fs.get_cwd()
|
|
|
|
|
self.log('OK CWD "%s".' % cwd)
|
|
|
|
|
self.respond('250 "%s" is the current directory.' % cwd)
|
|
|
|
|
except EnvironmentError, err:
|
|
|
|
|
self.log("Could not cwd: %s" % err)
|
|
|
|
|
if err.errno==2:
|
|
|
|
|
why = 'Authentication Required or Failed'
|
|
|
|
|
self.log('FAIL CWD "%s". %s.' %(self.fs.ftpnorm(line), why))
|
|
|
|
|
self.respond('530 %s.' %why)
|
|
|
|
|
else:
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL CWD "%s". %s.' %(self.fs.ftpnorm(line), why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
return
|
|
|
|
|
finally:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
|
|
|
|
|
def ftp_CDUP(self, line):
|
|
|
|
|
"""Change into the parent directory."""
|
|
|
|
@ -2556,21 +2580,17 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
"""
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='file')
|
|
|
|
|
datacr = self.get_crdata2(line, mode='file')
|
|
|
|
|
#if self.fs.isdir(datacr[1]):
|
|
|
|
|
# why = "%s is not retrievable" %line
|
|
|
|
|
# self.log('FAIL SIZE "%s". %s.' %(line, why))
|
|
|
|
|
# self.respond("550 %s." %why)
|
|
|
|
|
# self.fs.close_cr(datacr)
|
|
|
|
|
# return
|
|
|
|
|
size = self.run_as_current_user(self.fs.getsize, datacr)
|
|
|
|
|
except EnvironmentError, err:
|
|
|
|
|
why = err.strerror
|
|
|
|
|
self.log('FAIL SIZE "%s". %s.' %(line, why))
|
|
|
|
|
if err.errno == errno.ENOENT:
|
|
|
|
|
self.respond("404 %s." % why)
|
|
|
|
|
else:
|
|
|
|
|
self.respond('550 %s.' % why)
|
|
|
|
|
size = self.try_as_current_user(self.fs.getsize,(datacr,), line=line)
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
self.respond("213 %s" %size)
|
|
|
|
|
self.log('OK SIZE "%s".' %line)
|
|
|
|
@ -2581,36 +2601,35 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
3307 style timestamp (YYYYMMDDHHMMSS) as defined in RFC-3659.
|
|
|
|
|
"""
|
|
|
|
|
datacr = None
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line)
|
|
|
|
|
if not self.fs.isfile(datacr):
|
|
|
|
|
why = "%s is not retrievable" %line
|
|
|
|
|
self.log('FAIL MDTM "%s". %s.' %(line, why))
|
|
|
|
|
self.respond("550 %s." %why)
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
return
|
|
|
|
|
lmt = self.run_as_current_user(self.fs.getmtime, datacr)
|
|
|
|
|
if line.find('/', 1) < 0:
|
|
|
|
|
# root or db, just return local
|
|
|
|
|
lmt = None
|
|
|
|
|
else:
|
|
|
|
|
datacr = self.get_crdata2(line)
|
|
|
|
|
if not datacr:
|
|
|
|
|
raise IOError(errno.ENOENT, "%s is not retrievable" %line)
|
|
|
|
|
#if not self.fs.isfile(datacr[1]):
|
|
|
|
|
# raise IOError(errno.EPERM, "%s is not a regular file" % line)
|
|
|
|
|
|
|
|
|
|
lmt = self.try_as_current_user(self.fs.getmtime, (datacr,), line=line)
|
|
|
|
|
lmt = time.strftime("%Y%m%d%H%M%S", time.localtime(lmt))
|
|
|
|
|
self.respond("213 %s" %lmt)
|
|
|
|
|
self.log('OK MDTM "%s".' %line)
|
|
|
|
|
except OSError, err:
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL MDTM "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
return
|
|
|
|
|
finally:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
|
|
|
|
|
def ftp_MKD(self, line):
|
|
|
|
|
"""Create the specified directory."""
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='create')
|
|
|
|
|
self.run_as_current_user(self.fs.mkdir, datacr, datacr[2])
|
|
|
|
|
except IOError, err:
|
|
|
|
|
self.log('FAIL MKD "%s". %s.' %(line, err.strerror))
|
|
|
|
|
self.respond('550 %s.' % err.strerror)
|
|
|
|
|
except OSError, err:
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL MKD "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
datacr = self.get_crdata2(line, mode='create')
|
|
|
|
|
self.try_as_current_user(self.fs.mkdir, (datacr, datacr[2]), line=line)
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
self.log('OK MKD "%s".' %line)
|
|
|
|
|
self.respond("257 Directory created.")
|
|
|
|
@ -2620,39 +2639,30 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
"""Remove the specified directory."""
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='delete')
|
|
|
|
|
datacr = self.get_crdata2(line, mode='delete')
|
|
|
|
|
if not datacr[1]:
|
|
|
|
|
msg = "Can't remove root directory."
|
|
|
|
|
self.respond("550 %s" %msg)
|
|
|
|
|
self.respond("553 %s" %msg)
|
|
|
|
|
self.log('FAIL MKD "/". %s' %msg)
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
return
|
|
|
|
|
self.run_as_current_user(self.fs.rmdir, datacr)
|
|
|
|
|
except OSError, err:
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL RMD "%s". %s.' %(line, why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
else:
|
|
|
|
|
self.try_as_current_user(self.fs.rmdir, (datacr,), line=line)
|
|
|
|
|
self.log('OK RMD "%s".' %line)
|
|
|
|
|
self.respond("250 Directory removed.")
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
pass
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
|
|
|
|
|
def ftp_DELE(self, line):
|
|
|
|
|
"""Delete the specified file."""
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='delete')
|
|
|
|
|
self.run_as_current_user(self.fs.remove, datacr)
|
|
|
|
|
except EnvironmentError, err:
|
|
|
|
|
why = err.strerror
|
|
|
|
|
self.log('FAIL DELE "%s". %s.' %(line, why))
|
|
|
|
|
if err.errno == errno.ENOENT:
|
|
|
|
|
self.respond('404 %s.' % why)
|
|
|
|
|
else:
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
else:
|
|
|
|
|
datacr = self.get_crdata2(line, mode='delete')
|
|
|
|
|
self.try_as_current_user(self.fs.remove, (datacr,), line=line)
|
|
|
|
|
self.log('OK DELE "%s".' %line)
|
|
|
|
|
self.respond("250 File removed.")
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
pass
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
|
|
|
|
|
def ftp_RNFR(self, line):
|
|
|
|
@ -2660,16 +2670,16 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
here, see RNTO command)"""
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line, mode='rfnr')
|
|
|
|
|
datacr = self.get_crdata2(line, mode='rfnr')
|
|
|
|
|
if not datacr[1]:
|
|
|
|
|
self.respond("550 No such file or directory.")
|
|
|
|
|
elif not datacr[1]:
|
|
|
|
|
self.respond("550 Can't rename the home directory.")
|
|
|
|
|
self.respond("553 Can't rename the home directory.")
|
|
|
|
|
else:
|
|
|
|
|
self.fs.rnfr = datacr[1]
|
|
|
|
|
self.respond("350 Ready for destination name.")
|
|
|
|
|
except:
|
|
|
|
|
self.respond("550 Can't find the file or directory.")
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
pass
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
|
|
|
|
|
|
def ftp_RNTO(self, line):
|
|
|
|
@ -2681,21 +2691,17 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
return
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_crdata(line,'create')
|
|
|
|
|
oldname = self.fs.rnfr.path
|
|
|
|
|
if isinstance(oldname, (list, tuple)):
|
|
|
|
|
oldname = '/'.join(oldname)
|
|
|
|
|
self.run_as_current_user(self.fs.rename, self.fs.rnfr, datacr)
|
|
|
|
|
self.fs.rnfr = None
|
|
|
|
|
self.log('OK RNFR/RNTO "%s ==> %s".' % \
|
|
|
|
|
(_to_unicode(oldname), _to_unicode(line)))
|
|
|
|
|
self.respond("250 Renaming ok.")
|
|
|
|
|
except EnvironmentError, err:
|
|
|
|
|
why = _strerror(err)
|
|
|
|
|
self.log('FAIL RNFR/RNTO "%s ==> %s". %s.' \
|
|
|
|
|
% (_to_unicode(oldname), _to_unicode(line), why))
|
|
|
|
|
self.respond('550 %s.' %why)
|
|
|
|
|
datacr = self.get_crdata2(line,'create')
|
|
|
|
|
oldname = self.fs.rnfr.path
|
|
|
|
|
if isinstance(oldname, (list, tuple)):
|
|
|
|
|
oldname = '/'.join(oldname)
|
|
|
|
|
self.try_as_current_user(self.fs.rename, (self.fs.rnfr, datacr), line=line)
|
|
|
|
|
self.fs.rnfr = None
|
|
|
|
|
self.log('OK RNFR/RNTO "%s ==> %s".' % \
|
|
|
|
|
(_to_unicode(oldname), _to_unicode(line)))
|
|
|
|
|
self.respond("250 Renaming ok.")
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
pass
|
|
|
|
|
finally:
|
|
|
|
|
self.fs.rnfr = None
|
|
|
|
|
self.fs.close_cr(datacr)
|
|
|
|
@ -2784,9 +2790,9 @@ class FTPHandler(asynchat.async_chat):
|
|
|
|
|
datacr = None
|
|
|
|
|
try:
|
|
|
|
|
datacr = self.fs.get_cr(line)
|
|
|
|
|
iterator = self.run_as_current_user(self.fs.get_stat_dir, line, datacr)
|
|
|
|
|
except OSError, err:
|
|
|
|
|
self.respond('550 %s.' %_strerror(err))
|
|
|
|
|
iterator = self.try_as_current_user(self.fs.get_stat_dir, (line, datacr), line=line)
|
|
|
|
|
except FTPExceptionSent:
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
self.push('213-Status of "%s":\r\n' %self.fs.ftpnorm(line))
|
|
|
|
|
self.push_with_producer(BufferedIteratorProducer(iterator))
|
|
|
|
|