diff --git a/trytond/webdav/webdav.py b/trytond/webdav/webdav.py index 424cb1e0e1..8273ccb54b 100644 --- a/trytond/webdav/webdav.py +++ b/trytond/webdav/webdav.py @@ -12,12 +12,13 @@ class Directory(OSV): _description = __doc__ _columns = { 'name': fields.Char('Name', size=128, required=True, select=1), - 'parent': fields.Many2One('webdav.directory', 'Parent'), + 'parent': fields.Many2One('webdav.directory', 'Parent', + ondelete='restrict'), 'childs': fields.One2Many('webdav.directory', 'parent', 'Childs'), 'model': fields.Many2One('ir.model', 'Model'), 'domain': fields.Char('Domain', size=250), } - _default = { + _defaults = { 'domain': lambda *a: '[]', } _sql_constraints = [ @@ -30,6 +31,8 @@ class Directory(OSV): def _uri2object(self, cursor, user, uri, object_name=_name, object_id=False, context=None): + if not uri: + return self._name, False name, uri = (uri.split('/', 1) + [None])[0:2] if object_name == self._name: object_id = self.search(cursor, user, [ @@ -45,9 +48,13 @@ class Directory(OSV): else: if uri: return None, 0 - object_name = 'ir.attachment' - object_id = int(os.path.splitext(name)[0].rsplit('-', - 1)[1].strip()) + try: + object_id = int(os.path.splitext(name)[0].rsplit('-', + 1)[1].strip()) + object_name = 'ir.attachment' + except: + object_id = False + object_name = None else: if uri: if '/' in uri: @@ -76,7 +83,7 @@ class Directory(OSV): return res object_name, object_id = self._uri2object(cursor, user, uri, context=context) - if object_name == self._name: + if object_name == self._name and object_id: directory = self.browse(cursor, user, object_id, context=context) if directory.model: model_obj = self.pool.get(directory.model.model) @@ -147,7 +154,7 @@ class Directory(OSV): object_name, object_id = self._uri2object(cursor, user, uri, context=context) model_obj = self.pool.get(object_name) - if model_obj._log_access: + if model_obj._log_access and object_id: cursor.execute('SELECT EXTRACT(epoch FROM write_date) ' \ 'FROM "' + model_obj._table +'" ' \ 'WHERE id = %d', (object_id,)) @@ -166,10 +173,78 @@ class Directory(OSV): return base64.decodestring(attachment.datas) return DAV_NotFound + def put(self, cursor, user, uri, data, content_type, context=None): + from DAV.errors import DAV_Forbidden + from DAV.utils import get_uriparentpath, get_urifilename + object_name, object_id = self._uri2object(cursor, user, + get_uriparentpath(uri), context=context) + if object_name in ('ir.attachment') \ + or not object_id: + raise DAV_Forbidden + attachment_obj = self.pool.get('ir.attachment') + name = get_urifilename(uri) + try: + attachment_obj.create(cursor, user, { + 'name': name, + 'datas': base64.encodestring(data), + 'datas_fname': name, + 'res_model': object_name, + 'res_id': object_id, + }, context=context) + except: + raise DAV_Forbidden + return 201 + + def mkcol(self, cursor, user, uri, context=None): + from DAV.errors import DAV_Forbidden + from DAV.utils import get_uriparentpath, get_urifilename + if uri[-1:] == '/': + uri = uri[:-1] + object_name, object_id = self._uri2object(cursor, user, + get_uriparentpath(uri), context=context) + if object_name != 'webdav.directory': + raise DAV_Forbidden + name = get_urifilename(uri) + try: + self.create(cursor, user, { + 'name': name, + 'parent': object_id, + }, context=context) + except: + raise DAV_Forbidden + return 201 + + def rmcol(self, cursor, user, uri, context=None): + from DAV.errors import DAV_Forbidden + object_name, object_id = self._uri2object(cursor, user, uri, + context=context) + if object_name != 'webdav.directory' \ + or not object_id: + raise DAV_Forbidden + try: + self.unlink(cursor, user, object_id, context=context) + except: + raise DAV_Forbidden + return 200 + + def rm(self, cursor, user, uri, context=None): + from DAV.errors import DAV_Forbidden + object_name, object_id = self._uri2object(cursor, user, uri, + context=context) + if object_name != 'ir.attachment' \ + or not object_id: + raise DAV_Forbidden + model_obj = self.pool.get(object_name) + try: + model_obj.unlink(cursor, user, object_id, context=context) + except: + raise DAV_Forbidden + return 200 + def exists(self, cursor, user, uri, context=None): object_name, object_id = self._uri2object(cursor, user, uri, context=context) - if object_name: + if object_name and object_id: return 1 return None diff --git a/trytond/webdavsvc.py b/trytond/webdavsvc.py index 397695014c..4da275a20c 100644 --- a/trytond/webdavsvc.py +++ b/trytond/webdavsvc.py @@ -6,6 +6,7 @@ from DAV import AuthServer, WebDAVServer, iface from DAV.errors import * from DAV.constants import COLLECTION, OBJECT from DAV.utils import get_uriparentpath, get_urifilename +from DAV.davcmd import copyone, copytree, moveone, movetree, delone, deltree from netsvc import LocalService import security import pooler @@ -14,14 +15,21 @@ from version import PACKAGE, VERSION, WEBSITE # This work because there is only one thread USER_ID = 0 +# Fix for bad use of Document in DAV.utils make_xmlresponse +from DAV.utils import VERSION as DAV_VERSION +if DAV_VERSION == '0.6': + from xml.dom.Document import Document + Document.Document = Document class TrytonDAVInterface(iface.dav_interface): def __init__(self, interface, port): - self.baseuri = 'http://%s:%s/' % (interface or socket.getfqdn(), port) + self.baseuri = 'http://%s:%s/' % (interface or socket.gethostname(), port) def _get_dburi(self, uri): - uri = uri[len(self.baseuri):] + uri = urlparse.urlsplit(uri)[2] + if uri[0] == '/': + uri = uri[1:] dbname, uri = (uri.split('/', 1) + [None])[0:2] return dbname, uri @@ -40,6 +48,7 @@ class TrytonDAVInterface(iface.dav_interface): uri += '/' for child in directory_obj.get_childs(cursor, USER_ID, dburi): res.append(urlparse.urljoin(self.baseuri, uri + child)) + cursor.close() return res def get_data(self, uri): @@ -71,7 +80,46 @@ class TrytonDAVInterface(iface.dav_interface): pool = pooler.get_pool(dbname) cursor = pooler.get_db(dbname).cursor() directory_obj = pool.get('webdav.directory') - return directory_obj.get_data(cursor, USER_ID, dburi) + res = directory_obj.get_data(cursor, USER_ID, dburi) + cursor.close() + return res + + def put(self, uri, data, content_type=''): + dbname, dburi = self._get_dburi(uri) + if not dbname or not dburi: + raise DAV_Forbidden + pool = pooler.get_pool(dbname) + cursor = pooler.get_db(dbname).cursor() + directory_obj = pool.get('webdav.directory') + try: + try: + res = directory_obj.put(cursor, USER_ID, dburi, data, + content_type) + cursor.commit() + except: + cursor.rollback() + raise + finally: + cursor.close() + return res + + def mkcol(self, uri): + dbname, dburi = self._get_dburi(uri) + if not dbname or not dburi: + raise DAV_Forbidden + pool = pooler.get_pool(dbname) + cursor = pooler.get_db(dbname).cursor() + directory_obj = pool.get('webdav.directory') + try: + try: + res = directory_obj.mkcol(cursor, USER_ID, dburi) + cursor.commit() + except: + cursor.rollback() + raise + finally: + cursor.close() + return res def _get_dav_resourcetype(self, uri): dbname, dburi = self._get_dburi(uri) @@ -80,7 +128,9 @@ class TrytonDAVInterface(iface.dav_interface): pool = pooler.get_pool(dbname) cursor = pooler.get_db(dbname).cursor() directory_obj = pool.get('webdav.directory') - return directory_obj.get_resourcetype(cursor, USER_ID, dburi) + res = directory_obj.get_resourcetype(cursor, USER_ID, dburi) + cursor.close() + return res def _get_dav_displayname(self, uri): raise DAV_Secret @@ -92,7 +142,9 @@ class TrytonDAVInterface(iface.dav_interface): pool = pooler.get_pool(dbname) cursor = pooler.get_db(dbname).cursor() directory_obj = pool.get('webdav.directory') - return directory_obj.get_contentlength(cursor, USER_ID, dburi) + res = directory_obj.get_contentlength(cursor, USER_ID, dburi) + cursor.close() + return res def _get_dav_getcontenttype(self, uri): dbname, dburi = self._get_dburi(uri) @@ -101,7 +153,9 @@ class TrytonDAVInterface(iface.dav_interface): pool = pooler.get_pool(dbname) cursor = pooler.get_db(dbname).cursor() directory_obj = pool.get('webdav.directory') - return directory_obj.get_contenttype(cursor, USER_ID, dburi) + res = directory_obj.get_contenttype(cursor, USER_ID, dburi) + cursor.close() + return res def get_creationdate(self, uri): dbname, dburi = self._get_dburi(uri) @@ -110,7 +164,9 @@ class TrytonDAVInterface(iface.dav_interface): pool = pooler.get_pool(dbname) cursor = pooler.get_db(dbname).cursor() directory_obj = pool.get('webdav.directory') - return directory_obj.get_creationdate(cursor, USER_ID, dburi) + res = directory_obj.get_creationdate(cursor, USER_ID, dburi) + cursor.close() + return res def get_lastmodified(self, uri): dbname, dburi = self._get_dburi(uri) @@ -119,7 +175,45 @@ class TrytonDAVInterface(iface.dav_interface): pool = pooler.get_pool(dbname) cursor = pooler.get_db(dbname).cursor() directory_obj = pool.get('webdav.directory') - return directory_obj.get_lastmodified(cursor, USER_ID, dburi) + res = directory_obj.get_lastmodified(cursor, USER_ID, dburi) + cursor.close() + return res + + def rmcol(self, uri): + dbname, dburi = self._get_dburi(uri) + if not dbname or not dburi: + raise DAV_Forbidden + pool = pooler.get_pool(dbname) + cursor = pooler.get_db(dbname).cursor() + directory_obj = pool.get('webdav.directory') + try: + try: + res = directory_obj.rmcol(cursor, USER_ID, dburi) + cursor.commit() + except: + cursor.rollback() + raise + finally: + cursor.close() + return res + + def rm(self, uri): + dbname, dburi = self._get_dburi(uri) + if not dbname or not dburi: + raise DAV_Forbidden + pool = pooler.get_pool(dbname) + cursor = pooler.get_db(dbname).cursor() + directory_obj = pool.get('webdav.directory') + try: + try: + res = directory_obj.rm(cursor, USER_ID, dburi) + cursor.commit() + except: + cursor.rollback() + raise + finally: + cursor.close() + return res def exists(self, uri): dbname, dburi = self._get_dburi(uri) @@ -128,13 +222,42 @@ class TrytonDAVInterface(iface.dav_interface): pool = pooler.get_pool(dbname) cursor = pooler.get_db(dbname).cursor() directory_obj = pool.get('webdav.directory') - return directory_obj.exists(cursor, USER_ID, dburi) + res = directory_obj.exists(cursor, USER_ID, dburi) + cursor.close() + return res def is_collection(self, uri): if self._get_dav_resourcetype(uri) == COLLECTION: return 1 return 0 + def copyone(self, src, dst, overwrite): + return copyone(self, src, dst, overwrite) + + def copytree(self, src, dst, overwrite): + return copytree(self, src, dst, overwrite) + + def moveone(self, uri): + return moveone(self, uri) + + def movetree(self, src, dst, overwrite): + return movetree(self, src, dst, overwrite) + + def delone(self, uri): + return delone(self, uri) + + def deltree(self, uri): + return deltree(self, uri) + + def copy(self, src, dst): + content = self._get_dav_getcontenttype(src) + data = self.get_data(src) + self.put(dst, data, content) + return 201 + + def copycol(self, src, dst): + return self.mkcol(dst) + class WebDAVAuthRequestHandler(AuthServer.BufferedAuthRequestHandler, WebDAVServer.DAVRequestHandler):