[FIX] document_webdav : Replace <TAB> with four <WHITE SPACE>
authorHarry (Open ERP) <hmo@tinyerp.com>
Tue, 15 Dec 2009 14:31:05 +0000 (20:01 +0530)
committerHarry (Open ERP) <hmo@tinyerp.com>
Tue, 15 Dec 2009 14:31:05 +0000 (20:01 +0530)
bzr revid: hmo@tinyerp.com-20091215143105-3m1zuyf0fas65opf

addons/document_webdav/cache.py
addons/document_webdav/dav_fs.py
addons/document_webdav/webdav_server.py

index bc75114..7f03aa6 100644 (file)
@@ -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
 
index 4cd4b2d..0d8331b 100644 (file)
@@ -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
index f04315e..37ce38e 100644 (file)
@@ -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