bzr revid: hmo@tinyerp.com-20100717051300-ljwadjoh4jy6m1r1
This commit is contained in:
Harry (OpenERP) 2010-07-17 10:43:00 +05:30
commit fa3e08b9df
4 changed files with 163 additions and 155 deletions

View File

@ -615,8 +615,6 @@ class node_dir(node_database):
raise IOError(errno.EPERM, "Cannot move the root directory!")
self.parent = self.context.get_dir_node(cr, dbro.parent_id.id)
assert self.parent
# TODO: test if parent is writable.
if self.parent != ndir_node:
logger.debug('Cannot move dir %r from %r to %r', self, self.parent, ndir_node)
@ -624,6 +622,8 @@ class node_dir(node_database):
ret = {}
if new_name and (new_name != dbro.name):
if ndir_node.child(cr, new_name):
raise IOError(errno.EEXIST, "Destination path already exists")
ret['name'] = new_name
del dbro

View File

@ -403,7 +403,9 @@ class abstracted_fs(object):
# API shouldn't wait for us to write the object
assert (ret is True) or (ret is False)
cr.commit()
except Exception,err:
except EnvironmentError:
raise
except Exception, err:
self._log.exception('Cannot rename "%s" to "%s" at "%s"', src, datacr[2], datacr[1])
raise OSError(1,'Operation not permited.')

View File

@ -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))

View File

@ -106,7 +106,7 @@ class openerp_dav_handler(dav_interface):
except EnvironmentError, err:
if cr: cr.close()
import traceback
self.parent.log_error("Cannot %s: %s", opname, e.strerror)
self.parent.log_error("Cannot %s: %s", opname, err.strerror)
self.parent.log_message("Exc: %s",traceback.format_exc())
raise default_exc(err.strerror)
except Exception,e: