From 6082127d5da37e2a2314fe96e68ad413fa5af3bf Mon Sep 17 00:00:00 2001 From: "Harry (Open ERP)" Date: Tue, 15 Dec 2009 20:01:05 +0530 Subject: [PATCH] [FIX] document_webdav : Replace with four bzr revid: hmo@tinyerp.com-20091215143105-3m1zuyf0fas65opf --- addons/document_webdav/cache.py | 68 +- addons/document_webdav/dav_fs.py | 1132 +++++++++++++++---------------- addons/document_webdav/webdav_server.py | 44 +- 3 files changed, 622 insertions(+), 622 deletions(-) diff --git a/addons/document_webdav/cache.py b/addons/document_webdav/cache.py index bc75114..7f03aa6 100644 --- a/addons/document_webdav/cache.py +++ b/addons/document_webdav/cache.py @@ -2,38 +2,38 @@ import time import heapq def memoize(maxsize): - """decorator to 'memoize' a function - caching its results""" - def decorating_function(f): - cache = {} # map from key to value - heap = [] # list of keys, in LRU heap - cursize = 0 # because len() is slow - def wrapper(*args): - key = repr(args) - # performance crap - _cache=cache - _heap=heap - _heappop = heapq.heappop - _heappush = heapq.heappush - _time = time.time - _cursize = cursize - _maxsize = maxsize - if not _cache.has_key(key): - if _cursize == _maxsize: - # pop oldest element - (_,oldkey) = _heappop(_heap) - _cache.pop(oldkey) - else: - _cursize += 1 - # insert this element - _cache[key] = f(*args) - _heappush(_heap,(_time(),key)) - wrapper.misses += 1 - else: - wrapper.hits += 1 - return cache[key] - wrapper.__doc__ = f.__doc__ - wrapper.__name__ = f.__name__ - wrapper.hits = wrapper.misses = 0 - return wrapper - return decorating_function + """decorator to 'memoize' a function - caching its results""" + def decorating_function(f): + cache = {} # map from key to value + heap = [] # list of keys, in LRU heap + cursize = 0 # because len() is slow + def wrapper(*args): + key = repr(args) + # performance crap + _cache=cache + _heap=heap + _heappop = heapq.heappop + _heappush = heapq.heappush + _time = time.time + _cursize = cursize + _maxsize = maxsize + if not _cache.has_key(key): + if _cursize == _maxsize: + # pop oldest element + (_,oldkey) = _heappop(_heap) + _cache.pop(oldkey) + else: + _cursize += 1 + # insert this element + _cache[key] = f(*args) + _heappush(_heap,(_time(),key)) + wrapper.misses += 1 + else: + wrapper.hits += 1 + return cache[key] + wrapper.__doc__ = f.__doc__ + wrapper.__name__ = f.__name__ + wrapper.hits = wrapper.misses = 0 + return wrapper + return decorating_function diff --git a/addons/document_webdav/dav_fs.py b/addons/document_webdav/dav_fs.py index 4cd4b2d..0d8331b 100644 --- a/addons/document_webdav/dav_fs.py +++ b/addons/document_webdav/dav_fs.py @@ -56,33 +56,33 @@ urlparse.uses_netloc.append('webdav') urlparse.uses_netloc.append('webdavs') class tinydav_handler(dav_interface): - """ - This class models a Tiny ERP interface for the DAV server - """ - PROPS={'DAV:': dav_interface.PROPS['DAV:'], } + """ + This class models a Tiny ERP interface for the DAV server + """ + PROPS={'DAV:': dav_interface.PROPS['DAV:'], } - M_NS={ "DAV:" : dav_interface.M_NS['DAV:'], } + M_NS={ "DAV:" : dav_interface.M_NS['DAV:'], } - def __init__(self, parent, verbose=False): - self.db_name = False - self.directory_id=False - self.db_name_list=[] - self.parent = parent - self.baseuri = parent.baseuri + def __init__(self, parent, verbose=False): + self.db_name = False + self.directory_id=False + self.db_name_list=[] + self.parent = parent + self.baseuri = parent.baseuri def get_propnames(self,uri): - props = self.PROPS - self.parent.log_message('get propnames: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - if not dbname: - cr.close() - return props - node = self.uri2object(cr,uid,pool, uri2) - if node: - props.update(node.get_dav_props(cr)) - cr.close() - return props + props = self.PROPS + self.parent.log_message('get propnames: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + if not dbname: + cr.close() + return props + node = self.uri2object(cr,uid,pool, uri2) + if node: + props.update(node.get_dav_props(cr)) + cr.close() + return props def get_prop(self,uri,ns,propname): """ return the value of a given property @@ -97,557 +97,557 @@ class tinydav_handler(dav_interface): if uri[-1]=='/':uri=uri[:-1] cr, uid, pool, dbname, uri2 = self.get_cr(uri) if not dbname: - cr.close() + cr.close() raise DAV_NotFound node = self.uri2object(cr,uid,pool, uri2) if not node: - cr.close() + cr.close() raise DAV_NotFound res = node.get_dav_eprop(cr,ns,propname) cr.close() return res # -# def get_db(self,uri): -# names=self.uri2local(uri).split('/') -# self.db_name=False -# if len(names) > 1: -# self.db_name=self.uri2local(uri).split('/')[1] -# if self.db_name=='': -# raise Exception,'Plese specify Database name in folder' -# return self.db_name +# def get_db(self,uri): +# names=self.uri2local(uri).split('/') +# self.db_name=False +# if len(names) > 1: +# self.db_name=self.uri2local(uri).split('/')[1] +# if self.db_name=='': +# raise Exception,'Plese specify Database name in folder' +# return self.db_name # - def later_get_db_from_path(self,path): - return "aaa" - - def urijoin(self,*ajoin): - """ Return the base URI of this request, or even join it with the - ajoin path elements - """ - return self.baseuri+ '/'.join(ajoin) - - @memoize(4) - def db_list(self): - s = netsvc.LocalService('db') - result = s.list() - self.db_name_list=[] - for db_name in result: - db = pooler.get_db_only(db_name) - cr = db.cursor() - cr.execute("select id from ir_module_module where name = 'document' and state='installed' ") - res=cr.fetchone() - if res and len(res): - self.db_name_list.append(db_name) - cr.close() - return self.db_name_list - - def get_childs(self,uri): - """ return the child objects as self.baseuris for the given URI """ - self.parent.log_message('get childs: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - - if not dbname: - s = netsvc.LocalService('db') - return map(lambda x: self.urijoin(x), self.db_list()) - result = [] - node = self.uri2object(cr,uid,pool, uri2[:]) - if not node: - cr.close() - raise DAV_NotFound(uri2) - else: - fp = node.full_path() - if fp and len(fp): - self.parent.log_message('childs: @%s' % fp) - fp = '/'.join(fp) - else: - fp = None - for d in node.children(cr): - self.parent.log_message('child: %s' % d.path) - if fp: - result.append( self.urijoin(dbname,fp,d.path) ) - else: - result.append( self.urijoin(dbname,d.path) ) - cr.close() - return result - - def uri2local(self, uri): - uparts=urlparse.urlparse(uri) - reluri=uparts[2] - if reluri and reluri[-1]=="/": - reluri=reluri[:-1] - return reluri - - # - # pos: -1 to get the parent of the uri - # - def get_cr(self, uri): - pdb = self.parent.auth_proxy.last_auth - reluri = self.uri2local(uri) - try: - dbname = reluri.split('/')[2] - except: - dbname = False - if not dbname: - return None, None, None, False, None - if not pdb and dbname: - # if dbname was in our uri, we should have authenticated - # against that. - raise Exception("Programming error") - assert pdb == dbname, " %s != %s" %(pdb, dbname) - user, passwd, dbn2, uid = self.parent.auth_proxy.auth_creds[pdb] - db,pool = pooler.get_db_and_pool(dbname) - cr = db.cursor() - uri2 = reluri.split('/')[3:] - return cr, uid, pool, dbname, uri2 - - def uri2object(self, cr,uid, pool,uri): - if not uid: - return None - return pool.get('document.directory').get_object(cr, uid, uri) - - def get_data(self,uri): - self.parent.log_message('GET: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - try: - if not dbname: - raise DAV_Error, 409 - node = self.uri2object(cr,uid,pool, uri2) - if not node: - raise DAV_NotFound(uri2) - try: - datas = node.get_data(cr) - except TypeError,e: - import traceback - self.parent.log_error("GET typeError: %s", str(e)) - self.parent.log_message("Exc: %s",traceback.format_exc()) - raise DAV_Forbidden - except IndexError,e : - self.parent.log_error("GET IndexError: %s", str(e)) - raise DAV_NotFound(uri2) - except Exception,e: - import traceback - self.parent.log_error("GET exception: %s",str(e)) - self.parent.log_message("Exc: %s", traceback.format_exc()) - raise DAV_Error, 409 - return datas - finally: - cr.close() - - @memoize(CACHE_SIZE) - def _get_dav_resourcetype(self,uri): - """ return type of object """ - self.parent.log_message('get RT: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - try: - if not dbname: - return COLLECTION - node = self.uri2object(cr,uid,pool, uri2) - if not node: - raise DAV_NotFound(uri2) - if node.type in ('collection','database'): - return COLLECTION - return OBJECT - finally: - cr.close() - - def _get_dav_displayname(self,uri): - self.parent.log_message('get DN: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - if not dbname: - cr.close() - return COLLECTION - node = self.uri2object(cr,uid,pool, uri2) - if not node: - cr.close() - raise DAV_NotFound(uri2) - cr.close() - return node.displayname - - @memoize(CACHE_SIZE) - def _get_dav_getcontentlength(self,uri): - """ return the content length of an object """ - self.parent.log_message('get length: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - result = 0 - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - if not dbname: - cr.close() - return '0' - node = self.uri2object(cr, uid, pool, uri2) - if not node: - cr.close() - raise DAV_NotFound(uri2) - result = node.content_length or 0 - cr.close() - return str(result) - - @memoize(CACHE_SIZE) - def _get_dav_getetag(self,uri): - """ return the ETag of an object """ - self.parent.log_message('get etag: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - result = 0 - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - if not dbname: - cr.close() - return '0' - node = self.uri2object(cr, uid, pool, uri2) - if not node: - cr.close() - raise DAV_NotFound(uri2) - result = node.get_etag(cr) - cr.close() - return str(result) - - @memoize(CACHE_SIZE) - def get_lastmodified(self,uri): - """ return the last modified date of the object """ - if uri[-1]=='/':uri=uri[:-1] - today = time.time() - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - try: - if not dbname: - return today - node = self.uri2object(cr,uid,pool, uri2) - if not node: - raise DAV_NotFound(uri2) - if node.write_date: - return time.mktime(time.strptime(node.write_date,'%Y-%m-%d %H:%M:%S')) - else: - return today - finally: - cr.close() - - @memoize(CACHE_SIZE) - def get_creationdate(self,uri): - """ return the last modified date of the object """ - - if uri[-1]=='/':uri=uri[:-1] - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - try: - if not dbname: - raise DAV_Error, 409 - node = self.uri2object(cr,uid,pool, uri2) - if not node: - raise DAV_NotFound(uri2) - if node.create_date: - result = time.strptime(node.create_date,'%Y-%m-%d %H:%M:%S') - else: - result = time.gmtime() - return result - finally: - cr.close() - - @memoize(CACHE_SIZE) - def _get_dav_getcontenttype(self,uri): - self.parent.log_message('get contenttype: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - try: - if not dbname: - return 'httpd/unix-directory' - node = self.uri2object(cr,uid,pool, uri2) - if not node: - raise DAV_NotFound(uri2) - - result = 'application/octet-stream' - #if node.type=='collection': - #result ='httpd/unix-directory' - #else: - result = node.mimetype - return result - #raise DAV_NotFound, 'Could not find %s' % path - finally: - cr.close() - - def mkcol(self,uri): - """ create a new collection """ - self.parent.log_message('MKCOL: %s' % uri) - if uri[-1]=='/':uri=uri[:-1] - parent='/'.join(uri.split('/')[:-1]) - if not parent.startswith(self.baseuri): - parent=self.baseuri + ''.join(parent[1:]) - if not uri.startswith(self.baseuri): - uri=self.baseuri + ''.join(uri[1:]) - - - cr, uid, pool,dbname, uri2 = self.get_cr(uri) - if not dbname: - raise DAV_Error, 409 - node = self.uri2object(cr,uid,pool, uri2[:-1]) - object2=node and node.object2 or False - object=node and node.object or False - - objname = uri2[-1] - if not object: - pool.get('document.directory').create(cr, uid, { - 'name': objname, - 'parent_id': False, - 'ressource_type_id': False, - 'ressource_id': False - }) - else: - pool.get('document.directory').create(cr, uid, { - 'name': objname, - 'parent_id': object.id, - 'ressource_type_id': object.ressource_type_id.id, - 'ressource_id': object2 and object2.id or False - }) - - cr.commit() - cr.close() - return True - - def put(self,uri,data,content_type=None): - """ put the object into the filesystem """ - self.parent.log_message('Putting %s (%d), %s'%( unicode(uri,'utf8'), len(data), content_type)) - parent='/'.join(uri.split('/')[:-1]) - cr, uid, pool,dbname, uri2 = self.get_cr(uri) - if not dbname: - raise DAV_Forbidden - try: - node = self.uri2object(cr,uid,pool, uri2[:]) - except: - node = False - objname = uri2[-1] - ext = objname.find('.') >0 and objname.split('.')[1] or False - - if not node: - dir_node = self.uri2object(cr,uid,pool, uri2[:-1]) - if not dir_node: - raise DAV_NotFound('Parent folder not found') - try: - dir_node.create_child(cr,objname,data) - except Exception,e: - import traceback - self.parent.log_error("Cannot create %s: %s", objname, str(e)) - self.parent.log_message("Exc: %s",traceback.format_exc()) - raise DAV_Forbidden - else: - try: - node.set_data(cr,data) - except Exception,e: - import traceback - self.parent.log_error("Cannot save %s: %s", objname, str(e)) - self.parent.log_message("Exc: %s",traceback.format_exc()) - raise DAV_Forbidden - - cr.commit() - - return 201 - - def rmcol(self,uri): - """ delete a collection """ - if uri[-1]=='/':uri=uri[:-1] - - cr, uid, pool, dbname, uri2 = self.get_cr(uri) - if True or not dbname: # *-* - raise DAV_Error, 409 - node = self.uri2object(cr,uid,pool, uri2) - object2=node and node.object2 or False - object=node and node.object or False - if object._table_name=='document.directory': - if object.child_ids: - raise DAV_Forbidden # forbidden - if object.file_ids: - raise DAV_Forbidden # forbidden - res = pool.get('document.directory').unlink(cr, uid, [object.id]) - - cr.commit() - cr.close() - return 204 - - def rm(self,uri): - if uri[-1]=='/':uri=uri[:-1] - - object=False - cr, uid, pool,dbname, uri2 = self.get_cr(uri) - #if not dbname: - if True: - raise DAV_Error, 409 - node = self.uri2object(cr,uid,pool, uri2) - object2=node and node.object2 or False - object=node and node.object or False - if not object: - raise DAV_NotFound - - self.parent.log_message(' rm %s "%s"'%(object._table_name,uri)) - if object._table_name=='ir.attachment': - res = pool.get('ir.attachment').unlink(cr, uid, [object.id]) - else: - raise DAV_Forbidden # forbidden - parent='/'.join(uri.split('/')[:-1]) - cr.commit() - cr.close() - return 204 - - ### DELETE handlers (examples) - ### (we use the predefined methods in davcmd instead of doing - ### a rm directly - ### - - def delone(self,uri): - """ delete a single resource - - You have to return a result dict of the form - uri:error_code - or None if everything's ok - - """ - if uri[-1]=='/':uri=uri[:-1] - res=delone(self,uri) - parent='/'.join(uri.split('/')[:-1]) - return res - - def deltree(self,uri): - """ delete a collection - - You have to return a result dict of the form - uri:error_code - or None if everything's ok - """ - if uri[-1]=='/':uri=uri[:-1] - res=deltree(self,uri) - parent='/'.join(uri.split('/')[:-1]) - return res - - - ### - ### MOVE handlers (examples) - ### - - def moveone(self,src,dst,overwrite): - """ move one resource with Depth=0 - - an alternative implementation would be - - result_code=201 - if overwrite: - result_code=204 - r=os.system("rm -f '%s'" %dst) - if r: return 412 - r=os.system("mv '%s' '%s'" %(src,dst)) - if r: return 412 - return result_code - - (untested!). This would not use the davcmd functions - and thus can only detect errors directly on the root node. - """ - res=moveone(self,src,dst,overwrite) - return res - - def movetree(self,src,dst,overwrite): - """ move a collection with Depth=infinity - - an alternative implementation would be - - result_code=201 - if overwrite: - result_code=204 - r=os.system("rm -rf '%s'" %dst) - if r: return 412 - r=os.system("mv '%s' '%s'" %(src,dst)) - if r: return 412 - return result_code - - (untested!). This would not use the davcmd functions - and thus can only detect errors directly on the root node""" - - res=movetree(self,src,dst,overwrite) - return res - - ### - ### COPY handlers - ### - - def copyone(self,src,dst,overwrite): - """ copy one resource with Depth=0 - - an alternative implementation would be - - result_code=201 - if overwrite: - result_code=204 - r=os.system("rm -f '%s'" %dst) - if r: return 412 - r=os.system("cp '%s' '%s'" %(src,dst)) - if r: return 412 - return result_code - - (untested!). This would not use the davcmd functions - and thus can only detect errors directly on the root node. - """ - res=copyone(self,src,dst,overwrite) - return res - - def copytree(self,src,dst,overwrite): - """ copy a collection with Depth=infinity - - an alternative implementation would be - - result_code=201 - if overwrite: - result_code=204 - r=os.system("rm -rf '%s'" %dst) - if r: return 412 - r=os.system("cp -r '%s' '%s'" %(src,dst)) - if r: return 412 - return result_code - - (untested!). This would not use the davcmd functions - and thus can only detect errors directly on the root node""" - res=copytree(self,src,dst,overwrite) - return res - - ### - ### copy methods. - ### This methods actually copy something. low-level - ### They are called by the davcmd utility functions - ### copytree and copyone (not the above!) - ### Look in davcmd.py for further details. - ### - - def copy(self,src,dst): - src=urllib.unquote(src) - dst=urllib.unquote(dst) - ct = self._get_dav_getcontenttype(src) - data = self.get_data(src) - self.put(dst,data,ct) - return 201 - - def copycol(self,src,dst): - """ copy a collection. - - As this is not recursive (the davserver recurses itself) - we will only create a new directory here. For some more - advanced systems we might also have to copy properties from - the source to the destination. - """ - print " copy a collection." - return self.mkcol(dst) - - - def exists(self,uri): - """ test if a resource exists """ - result = False - cr, uid, pool,dbname, uri2 = self.get_cr(uri) - if not dbname: - return True - try: - node = self.uri2object(cr,uid,pool, uri2) - if node: - result = True - except: - pass - cr.close() - return result - - @memoize(CACHE_SIZE) - def is_collection(self,uri): - """ test if the given uri is a collection """ - return self._get_dav_resourcetype(uri)==COLLECTION + def later_get_db_from_path(self,path): + return "aaa" + + def urijoin(self,*ajoin): + """ Return the base URI of this request, or even join it with the + ajoin path elements + """ + return self.baseuri+ '/'.join(ajoin) + + @memoize(4) + def db_list(self): + s = netsvc.LocalService('db') + result = s.list() + self.db_name_list=[] + for db_name in result: + db = pooler.get_db_only(db_name) + cr = db.cursor() + cr.execute("select id from ir_module_module where name = 'document' and state='installed' ") + res=cr.fetchone() + if res and len(res): + self.db_name_list.append(db_name) + cr.close() + return self.db_name_list + + def get_childs(self,uri): + """ return the child objects as self.baseuris for the given URI """ + self.parent.log_message('get childs: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + + if not dbname: + s = netsvc.LocalService('db') + return map(lambda x: self.urijoin(x), self.db_list()) + result = [] + node = self.uri2object(cr,uid,pool, uri2[:]) + if not node: + cr.close() + raise DAV_NotFound(uri2) + else: + fp = node.full_path() + if fp and len(fp): + self.parent.log_message('childs: @%s' % fp) + fp = '/'.join(fp) + else: + fp = None + for d in node.children(cr): + self.parent.log_message('child: %s' % d.path) + if fp: + result.append( self.urijoin(dbname,fp,d.path) ) + else: + result.append( self.urijoin(dbname,d.path) ) + cr.close() + return result + + def uri2local(self, uri): + uparts=urlparse.urlparse(uri) + reluri=uparts[2] + if reluri and reluri[-1]=="/": + reluri=reluri[:-1] + return reluri + + # + # pos: -1 to get the parent of the uri + # + def get_cr(self, uri): + pdb = self.parent.auth_proxy.last_auth + reluri = self.uri2local(uri) + try: + dbname = reluri.split('/')[2] + except: + dbname = False + if not dbname: + return None, None, None, False, None + if not pdb and dbname: + # if dbname was in our uri, we should have authenticated + # against that. + raise Exception("Programming error") + assert pdb == dbname, " %s != %s" %(pdb, dbname) + user, passwd, dbn2, uid = self.parent.auth_proxy.auth_creds[pdb] + db,pool = pooler.get_db_and_pool(dbname) + cr = db.cursor() + uri2 = reluri.split('/')[3:] + return cr, uid, pool, dbname, uri2 + + def uri2object(self, cr,uid, pool,uri): + if not uid: + return None + return pool.get('document.directory').get_object(cr, uid, uri) + + def get_data(self,uri): + self.parent.log_message('GET: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + try: + if not dbname: + raise DAV_Error, 409 + node = self.uri2object(cr,uid,pool, uri2) + if not node: + raise DAV_NotFound(uri2) + try: + datas = node.get_data(cr) + except TypeError,e: + import traceback + self.parent.log_error("GET typeError: %s", str(e)) + self.parent.log_message("Exc: %s",traceback.format_exc()) + raise DAV_Forbidden + except IndexError,e : + self.parent.log_error("GET IndexError: %s", str(e)) + raise DAV_NotFound(uri2) + except Exception,e: + import traceback + self.parent.log_error("GET exception: %s",str(e)) + self.parent.log_message("Exc: %s", traceback.format_exc()) + raise DAV_Error, 409 + return datas + finally: + cr.close() + + @memoize(CACHE_SIZE) + def _get_dav_resourcetype(self,uri): + """ return type of object """ + self.parent.log_message('get RT: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + try: + if not dbname: + return COLLECTION + node = self.uri2object(cr,uid,pool, uri2) + if not node: + raise DAV_NotFound(uri2) + if node.type in ('collection','database'): + return COLLECTION + return OBJECT + finally: + cr.close() + + def _get_dav_displayname(self,uri): + self.parent.log_message('get DN: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + if not dbname: + cr.close() + return COLLECTION + node = self.uri2object(cr,uid,pool, uri2) + if not node: + cr.close() + raise DAV_NotFound(uri2) + cr.close() + return node.displayname + + @memoize(CACHE_SIZE) + def _get_dav_getcontentlength(self,uri): + """ return the content length of an object """ + self.parent.log_message('get length: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + result = 0 + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + if not dbname: + cr.close() + return '0' + node = self.uri2object(cr, uid, pool, uri2) + if not node: + cr.close() + raise DAV_NotFound(uri2) + result = node.content_length or 0 + cr.close() + return str(result) + + @memoize(CACHE_SIZE) + def _get_dav_getetag(self,uri): + """ return the ETag of an object """ + self.parent.log_message('get etag: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + result = 0 + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + if not dbname: + cr.close() + return '0' + node = self.uri2object(cr, uid, pool, uri2) + if not node: + cr.close() + raise DAV_NotFound(uri2) + result = node.get_etag(cr) + cr.close() + return str(result) + + @memoize(CACHE_SIZE) + def get_lastmodified(self,uri): + """ return the last modified date of the object """ + if uri[-1]=='/':uri=uri[:-1] + today = time.time() + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + try: + if not dbname: + return today + node = self.uri2object(cr,uid,pool, uri2) + if not node: + raise DAV_NotFound(uri2) + if node.write_date: + return time.mktime(time.strptime(node.write_date,'%Y-%m-%d %H:%M:%S')) + else: + return today + finally: + cr.close() + + @memoize(CACHE_SIZE) + def get_creationdate(self,uri): + """ return the last modified date of the object """ + + if uri[-1]=='/':uri=uri[:-1] + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + try: + if not dbname: + raise DAV_Error, 409 + node = self.uri2object(cr,uid,pool, uri2) + if not node: + raise DAV_NotFound(uri2) + if node.create_date: + result = time.strptime(node.create_date,'%Y-%m-%d %H:%M:%S') + else: + result = time.gmtime() + return result + finally: + cr.close() + + @memoize(CACHE_SIZE) + def _get_dav_getcontenttype(self,uri): + self.parent.log_message('get contenttype: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + try: + if not dbname: + return 'httpd/unix-directory' + node = self.uri2object(cr,uid,pool, uri2) + if not node: + raise DAV_NotFound(uri2) + + result = 'application/octet-stream' + #if node.type=='collection': + #result ='httpd/unix-directory' + #else: + result = node.mimetype + return result + #raise DAV_NotFound, 'Could not find %s' % path + finally: + cr.close() + + def mkcol(self,uri): + """ create a new collection """ + self.parent.log_message('MKCOL: %s' % uri) + if uri[-1]=='/':uri=uri[:-1] + parent='/'.join(uri.split('/')[:-1]) + if not parent.startswith(self.baseuri): + parent=self.baseuri + ''.join(parent[1:]) + if not uri.startswith(self.baseuri): + uri=self.baseuri + ''.join(uri[1:]) + + + cr, uid, pool,dbname, uri2 = self.get_cr(uri) + if not dbname: + raise DAV_Error, 409 + node = self.uri2object(cr,uid,pool, uri2[:-1]) + object2=node and node.object2 or False + object=node and node.object or False + + objname = uri2[-1] + if not object: + pool.get('document.directory').create(cr, uid, { + 'name': objname, + 'parent_id': False, + 'ressource_type_id': False, + 'ressource_id': False + }) + else: + pool.get('document.directory').create(cr, uid, { + 'name': objname, + 'parent_id': object.id, + 'ressource_type_id': object.ressource_type_id.id, + 'ressource_id': object2 and object2.id or False + }) + + cr.commit() + cr.close() + return True + + def put(self,uri,data,content_type=None): + """ put the object into the filesystem """ + self.parent.log_message('Putting %s (%d), %s'%( unicode(uri,'utf8'), len(data), content_type)) + parent='/'.join(uri.split('/')[:-1]) + cr, uid, pool,dbname, uri2 = self.get_cr(uri) + if not dbname: + raise DAV_Forbidden + try: + node = self.uri2object(cr,uid,pool, uri2[:]) + except: + node = False + objname = uri2[-1] + ext = objname.find('.') >0 and objname.split('.')[1] or False + + if not node: + dir_node = self.uri2object(cr,uid,pool, uri2[:-1]) + if not dir_node: + raise DAV_NotFound('Parent folder not found') + try: + dir_node.create_child(cr,objname,data) + except Exception,e: + import traceback + self.parent.log_error("Cannot create %s: %s", objname, str(e)) + self.parent.log_message("Exc: %s",traceback.format_exc()) + raise DAV_Forbidden + else: + try: + node.set_data(cr,data) + except Exception,e: + import traceback + self.parent.log_error("Cannot save %s: %s", objname, str(e)) + self.parent.log_message("Exc: %s",traceback.format_exc()) + raise DAV_Forbidden + + cr.commit() + + return 201 + + def rmcol(self,uri): + """ delete a collection """ + if uri[-1]=='/':uri=uri[:-1] + + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + if True or not dbname: # *-* + raise DAV_Error, 409 + node = self.uri2object(cr,uid,pool, uri2) + object2=node and node.object2 or False + object=node and node.object or False + if object._table_name=='document.directory': + if object.child_ids: + raise DAV_Forbidden # forbidden + if object.file_ids: + raise DAV_Forbidden # forbidden + res = pool.get('document.directory').unlink(cr, uid, [object.id]) + + cr.commit() + cr.close() + return 204 + + def rm(self,uri): + if uri[-1]=='/':uri=uri[:-1] + + object=False + cr, uid, pool,dbname, uri2 = self.get_cr(uri) + #if not dbname: + if True: + raise DAV_Error, 409 + node = self.uri2object(cr,uid,pool, uri2) + object2=node and node.object2 or False + object=node and node.object or False + if not object: + raise DAV_NotFound + + self.parent.log_message(' rm %s "%s"'%(object._table_name,uri)) + if object._table_name=='ir.attachment': + res = pool.get('ir.attachment').unlink(cr, uid, [object.id]) + else: + raise DAV_Forbidden # forbidden + parent='/'.join(uri.split('/')[:-1]) + cr.commit() + cr.close() + return 204 + + ### DELETE handlers (examples) + ### (we use the predefined methods in davcmd instead of doing + ### a rm directly + ### + + def delone(self,uri): + """ delete a single resource + + You have to return a result dict of the form + uri:error_code + or None if everything's ok + + """ + if uri[-1]=='/':uri=uri[:-1] + res=delone(self,uri) + parent='/'.join(uri.split('/')[:-1]) + return res + + def deltree(self,uri): + """ delete a collection + + You have to return a result dict of the form + uri:error_code + or None if everything's ok + """ + if uri[-1]=='/':uri=uri[:-1] + res=deltree(self,uri) + parent='/'.join(uri.split('/')[:-1]) + return res + + + ### + ### MOVE handlers (examples) + ### + + def moveone(self,src,dst,overwrite): + """ move one resource with Depth=0 + + an alternative implementation would be + + result_code=201 + if overwrite: + result_code=204 + r=os.system("rm -f '%s'" %dst) + if r: return 412 + r=os.system("mv '%s' '%s'" %(src,dst)) + if r: return 412 + return result_code + + (untested!). This would not use the davcmd functions + and thus can only detect errors directly on the root node. + """ + res=moveone(self,src,dst,overwrite) + return res + + def movetree(self,src,dst,overwrite): + """ move a collection with Depth=infinity + + an alternative implementation would be + + result_code=201 + if overwrite: + result_code=204 + r=os.system("rm -rf '%s'" %dst) + if r: return 412 + r=os.system("mv '%s' '%s'" %(src,dst)) + if r: return 412 + return result_code + + (untested!). This would not use the davcmd functions + and thus can only detect errors directly on the root node""" + + res=movetree(self,src,dst,overwrite) + return res + + ### + ### COPY handlers + ### + + def copyone(self,src,dst,overwrite): + """ copy one resource with Depth=0 + + an alternative implementation would be + + result_code=201 + if overwrite: + result_code=204 + r=os.system("rm -f '%s'" %dst) + if r: return 412 + r=os.system("cp '%s' '%s'" %(src,dst)) + if r: return 412 + return result_code + + (untested!). This would not use the davcmd functions + and thus can only detect errors directly on the root node. + """ + res=copyone(self,src,dst,overwrite) + return res + + def copytree(self,src,dst,overwrite): + """ copy a collection with Depth=infinity + + an alternative implementation would be + + result_code=201 + if overwrite: + result_code=204 + r=os.system("rm -rf '%s'" %dst) + if r: return 412 + r=os.system("cp -r '%s' '%s'" %(src,dst)) + if r: return 412 + return result_code + + (untested!). This would not use the davcmd functions + and thus can only detect errors directly on the root node""" + res=copytree(self,src,dst,overwrite) + return res + + ### + ### copy methods. + ### This methods actually copy something. low-level + ### They are called by the davcmd utility functions + ### copytree and copyone (not the above!) + ### Look in davcmd.py for further details. + ### + + def copy(self,src,dst): + src=urllib.unquote(src) + dst=urllib.unquote(dst) + ct = self._get_dav_getcontenttype(src) + data = self.get_data(src) + self.put(dst,data,ct) + return 201 + + def copycol(self,src,dst): + """ copy a collection. + + As this is not recursive (the davserver recurses itself) + we will only create a new directory here. For some more + advanced systems we might also have to copy properties from + the source to the destination. + """ + print " copy a collection." + return self.mkcol(dst) + + + def exists(self,uri): + """ test if a resource exists """ + result = False + cr, uid, pool,dbname, uri2 = self.get_cr(uri) + if not dbname: + return True + try: + node = self.uri2object(cr,uid,pool, uri2) + if node: + result = True + except: + pass + cr.close() + return result + + @memoize(CACHE_SIZE) + def is_collection(self,uri): + """ test if the given uri is a collection """ + return self._get_dav_resourcetype(uri)==COLLECTION diff --git a/addons/document_webdav/webdav_server.py b/addons/document_webdav/webdav_server.py index f04315e..37ce38e 100644 --- a/addons/document_webdav/webdav_server.py +++ b/addons/document_webdav/webdav_server.py @@ -35,13 +35,13 @@ from service.websrv_lib import HTTPDir,FixSendError class DAVHandler(FixSendError,DAVRequestHandler): verbose = False - + def get_userinfo(self,user,pw): - print "get_userinfo" - return False + print "get_userinfo" + return False def _log(self, message): - netsvc.Logger().notifyChannel("webdav",netsvc.LOG_DEBUG,message) - + netsvc.Logger().notifyChannel("webdav",netsvc.LOG_DEBUG,message) + def handle(self): pass @@ -49,30 +49,30 @@ class DAVHandler(FixSendError,DAVRequestHandler): pass def setup(self): - davpath = '/'+config.get_misc('webdav','vdir','webdav')+'/' - self.baseuri = "http://%s:%d%s"% (self.server.server_name,self.server.server_port,davpath) - self.IFACE_CLASS = tinydav_handler(self) - pass - + davpath = '/'+config.get_misc('webdav','vdir','webdav')+'/' + self.baseuri = "http://%s:%d%s"% (self.server.server_name,self.server.server_port,davpath) + self.IFACE_CLASS = tinydav_handler(self) + pass + def log_message(self, format, *args): - netsvc.Logger().notifyChannel('webdav',netsvc.LOG_DEBUG_RPC,format % args) + netsvc.Logger().notifyChannel('webdav',netsvc.LOG_DEBUG_RPC,format % args) def log_error(self, format, *args): - netsvc.Logger().notifyChannel('xmlrpc',netsvc.LOG_WARNING,format % args) + netsvc.Logger().notifyChannel('xmlrpc',netsvc.LOG_WARNING,format % args) try: - from service.http_server import reg_http_service,OpenERPAuthProvider - if (config.get_misc('webdav','enable',False)): - davpath = '/'+config.get_misc('webdav','vdir','webdav')+'/' - handler = DAVHandler - handler.verbose = config.get_misc('webdav','verbose',True) - handler.debug = config.get_misc('webdav','debug',True) - reg_http_service(HTTPDir(davpath,DAVHandler,OpenERPAuthProvider())) - netsvc.Logger().notifyChannel('webdav',netsvc.LOG_INFO,"WebDAV service registered at path: %s/ "% davpath) + from service.http_server import reg_http_service,OpenERPAuthProvider + if (config.get_misc('webdav','enable',False)): + davpath = '/'+config.get_misc('webdav','vdir','webdav')+'/' + handler = DAVHandler + handler.verbose = config.get_misc('webdav','verbose',True) + handler.debug = config.get_misc('webdav','debug',True) + reg_http_service(HTTPDir(davpath,DAVHandler,OpenERPAuthProvider())) + netsvc.Logger().notifyChannel('webdav',netsvc.LOG_INFO,"WebDAV service registered at path: %s/ "% davpath) except Exception, e: - logger = netsvc.Logger() - logger.notifyChannel('webdav', netsvc.LOG_ERROR, 'Cannot launch webdav: %s' % e) + logger = netsvc.Logger() + logger.notifyChannel('webdav', netsvc.LOG_ERROR, 'Cannot launch webdav: %s' % e) #eof -- 1.7.10.4