diff --git a/addons/document/nodes.py b/addons/document/nodes.py index de2a83285f9..228f104574d 100644 --- a/addons/document/nodes.py +++ b/addons/document/nodes.py @@ -314,6 +314,14 @@ class node_class(object): logger.debug('Property %s not supported' % prop, exc_info=True) return None + def get_dav_resourcetype(self, cr): + """ Get the DAV resource type. + + Is here because some nodes may exhibit special behaviour, like + CalDAV/GroupDAV collections + """ + raise NotImplementedError + def move_to(self, cr, ndir_node, new_name=False, fil_obj=None, ndir_obj=None, in_write=False): """ Move this node to a new parent directory. @param ndir_node the collection that this node should be moved under @@ -456,6 +464,9 @@ class node_database(node_class): def _get_ttag(self,cr): return 'db-%s' % cr.dbname + def get_dav_resourcetype(self, cr): + return ('collection', 'DAV:') + def mkdosname(company_name, default='noname'): """ convert a string to a dos-like name""" if not company_name: @@ -778,6 +789,9 @@ class node_res_dir(node_class): def _get_ttag(self,cr): return 'rdir-%d' % self.dir_id + def get_dav_resourcetype(self, cr): + return ('collection', 'DAV:') + class node_res_obj(node_class): """ A special sibling to node_dir, which does only contain dynamically created folders foreach resource in the foreign model. @@ -1034,6 +1048,9 @@ class node_res_obj(node_class): def _get_ttag(self,cr): return 'rodir-%d-%d' % (self.dir_id, self.res_id) + def get_dav_resourcetype(self, cr): + return ('collection', 'DAV:') + class node_file(node_class): our_type = 'file' def __init__(self, path, parent, context, fil): @@ -1168,6 +1185,9 @@ class node_file(node_class): def _get_ttag(self,cr): return 'file-%d' % self.file_id + def get_dav_resourcetype(self, cr): + return '' + def move_to(self, cr, ndir_node, new_name=False, fil_obj=None, ndir_obj=None, in_write=False): if ndir_node.context != self.context: raise NotImplementedError("Cannot move files between contexts") @@ -1313,6 +1333,8 @@ class node_content(node_class): def _get_ttag(self,cr): return 'cnt-%d%s' % (self.cnt_id,(self.act_id and ('-' + str(self.act_id))) or '') + def get_dav_resourcetype(self, cr): + return '' class nodefd_content(StringIO, node_descriptor): """ A descriptor to content nodes diff --git a/addons/document_webdav/dav_fs.py b/addons/document_webdav/dav_fs.py index 78812ff8cf5..af8738ef0da 100644 --- a/addons/document_webdav/dav_fs.py +++ b/addons/document_webdav/dav_fs.py @@ -370,19 +370,22 @@ class openerp_dav_handler(dav_interface): if cr: cr.close() @memoize(CACHE_SIZE) - def _get_dav_resourcetype(self,uri): + def _get_dav_resourcetype(self, uri): """ return type of object """ self.parent.log_message('get RT: %s' % uri) cr, uid, pool, dbname, uri2 = self.get_cr(uri) try: if not dbname: return COLLECTION - node = self.uri2object(cr,uid,pool, uri2) + node = self.uri2object(cr, uid, pool, uri2) if not node: raise DAV_NotFound2(uri2) - if node.type in ('collection','database'): - return COLLECTION - return OBJECT + try: + return node.get_dav_resourcetype(cr) + except NotImplementedError: + if node.type in ('collection','database'): + return ('collection', 'DAV:') + return '' finally: if cr: cr.close() @@ -739,6 +742,17 @@ class openerp_dav_handler(dav_interface): @memoize(CACHE_SIZE) def is_collection(self, uri): """ test if the given uri is a collection """ - return self._get_dav_resourcetype(uri)==COLLECTION + cr, uid, pool, dbname, uri2 = self.get_cr(uri) + try: + if not dbname: + return True + node = self.uri2object(cr,uid,pool, uri2) + if not node: + raise DAV_NotFound2(uri2) + if node.type in ('collection','database'): + return True + return False + finally: + if cr: cr.close() #eof diff --git a/addons/document_webdav/webdav.py b/addons/document_webdav/webdav.py index 1502ff204f8..1fd530cbdca 100644 --- a/addons/document_webdav/webdav.py +++ b/addons/document_webdav/webdav.py @@ -48,6 +48,70 @@ def mk_prop_response(self, uri, good_props, bad_props, doc): re.setAttribute("xmlns:ns"+str(nsnum),nsname) nsnum=nsnum+1 + def _prop_child(xnode, ns, prop, value): + """Append a property xml node to xnode, with value + + And a little smarter than that, it will consider namespace and + also allow nested properties etc. + + :param ns the namespace of the node + :param prop the name of the property + :param value the value. Can be: + string: text node + tuple ('elem', 'ns') for empty sub-node + tuple ('elem', 'ns', sub-elems) for sub-node with elements + list, of above tuples + """ + if ns == 'DAV:': + ns_prefix = 'D:' + else: + ns_prefix="ns"+str(namespaces.index(ns))+":" + + pe=doc.createElement(ns_prefix+str(prop)) + if hasattr(value, '__class__') and value.__class__.__name__ == 'Element': + pe.appendChild(value) + else: + if ns == 'DAV:' and prop=="resourcetype" and isinstance(value, int): + # hack, to go.. + if value == 1: + ve=doc.createElement("D:collection") + pe.appendChild(ve) + else: + _prop_elem_child(pe, ns, value, ns_prefix) + + xnode.appendChild(pe) + + def _prop_elem_child(pnode, pns, v, pns_prefix): + + if isinstance(v, list): + for vit in v: + _prop_elem_child(pnode, pns, vit, pns_prefix) + elif isinstance(v,tuple): + need_ns = False + if v[1] == pns: + ns_prefix = pns_prefix + elif v[1] == 'DAV:': + ns_prefix = 'D:' + elif v[1] in namespaces: + ns_prefix="ns"+str(namespaces.index(v[1]))+":" + else: + # namespaces.append(v[1]) + # nsnum += 1 + ns_prefix="ns"+str(nsnum)+":" + need_ns = True + + ve=doc.createElement(ns_prefix+v[0]) + if need_ns: + ve.setAttribute("xmlns:ns"+str(nsnum), v[1]) + if len(v) > 2 and isinstance(v[2], list): + # support nested elements like: + # ( 'elem', 'ns:', [('sub-elem1', 'ns1'), ...] + _prop_elem_child(ve, v[1], v[2], ns_prefix) + pnode.appendChild(ve) + else: + ve=doc.createTextNode(tools.ustr(v)) + pnode.appendChild(ve) + # write href information uparts=urlparse.urlparse(uri) fileloc=uparts[2] @@ -74,22 +138,7 @@ def mk_prop_response(self, uri, good_props, bad_props, doc): for p,v in good_props[ns].items(): if not v: continue - pe=doc.createElement(ns_prefix+str(p)) - if hasattr(v, '__class__') and v.__class__.__name__ == 'Element': - pe.appendChild(v) - else: - if ns == 'DAV:' and p=="resourcetype": - if v == 1: - ve=doc.createElement("D:collection") - pe.appendChild(ve) - elif isinstance(v,tuple) and v[1] == ns: - ve=doc.createElement(ns_prefix+v[0]) - pe.appendChild(ve) - else: - ve=doc.createTextNode(tools.ustr(v)) - pe.appendChild(ve) - - gp.appendChild(pe) + _prop_child(gp, ns, p, v) ps.appendChild(gp) s=doc.createElement("D:status")